Compare commits
1 commit
extension-
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cfe4dbdeb |
14
src/app.html
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<title>EaglerBuilder - Make mods with blocks</title>
|
||||
<title>EaglerForge Builder - Make mods with blocks</title>
|
||||
<meta name="description" content="Create EaglerForge mods using Scratch-like block coding." />
|
||||
<meta name="keywords" content="EaglerForge, Eaglercraft, blocks, EaglerForge mod, Minecraft" />
|
||||
<meta name="author" content="Oeildelynx" />
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
<meta name="viewport" content="width=device-width" />
|
||||
<style id="XTI0GZwZotMzDMi0wcGctLFttIWctMdtLPXI9M0aGGDQyMHRpMViW3E="></style>
|
||||
<style>
|
||||
*:not(code, textarea, .token) {
|
||||
*:not(code, .token) {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
body {
|
||||
|
|
@ -24,15 +24,13 @@
|
|||
}
|
||||
|
||||
a {
|
||||
color: rgb(86, 114, 205);
|
||||
text-decoration: none;
|
||||
color: #ff4b4b;
|
||||
}
|
||||
a:hover {
|
||||
color: rgb(126, 154, 245);
|
||||
text-decoration: underline;
|
||||
color: #ff7373;
|
||||
}
|
||||
a:active {
|
||||
color: rgb(54, 82, 173);
|
||||
color: #a52b2b;
|
||||
}
|
||||
|
||||
/* blockly overrides */
|
||||
|
|
@ -116,7 +114,7 @@
|
|||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div class="__alert_prompt" id="Zm5BSEgzQW5HeW9yZkFkNEhpbGJiamtpZmdoOGNDc2lMR29JSzF0K2JnPT0=">
|
||||
<p style="margin-block: 0;">EaglerBuilder is currently in development, some project files may break due to code changing all the time.</p>
|
||||
<p style="margin-block: 0;">EaglerForge Builder is currently in development, some project files may break due to code changing all the time.</p>
|
||||
<button
|
||||
style="margin: 0; margin-left: 8px; background: transparent; border: 0; outline: 0; padding: 0; cursor: pointer;"
|
||||
onclick="closeAlert()"
|
||||
|
|
|
|||
74
src/lib/Documentation/Documentation.svelte
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<script>
|
||||
//import EaglerForge from "$lib/EaglerCraft/EaglerCraft.svelte";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function event() {
|
||||
dispatch("click");
|
||||
}
|
||||
|
||||
</script>
|
||||
<div id="documentation" opened="false">
|
||||
<button onclick="closeDoc()" id="closeDocButton" opened="false">×</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#documentation{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
height: calc(100% - 16px);
|
||||
width: 0%;
|
||||
z-index: 1;
|
||||
transition: width 0.5s ease-out;
|
||||
border: none;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
:global(body.dark) #documentation{
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
#documentation:not([opened="false"]){
|
||||
border-left: 1px solid #c6c6c6;
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
:global(body.dark) #documentation:not([opened="false"]){
|
||||
border-left: 1px solid #575757;
|
||||
}
|
||||
|
||||
|
||||
#closeDocButton {
|
||||
position: absolute;
|
||||
border: 0px;
|
||||
background-color: transparent;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
transform: translateX(100px);
|
||||
font-size: 2rem;
|
||||
transition: transform 0.5s ease-out;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#closeDocButton:not([opened="false"]) {
|
||||
transform: translate(0px);
|
||||
}
|
||||
|
||||
:global(body.dark) #closeDocButton {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:global(.fa.fa-expand, .fa.fa-compress) {
|
||||
vertical-align: text-bottom;
|
||||
font-size: large;
|
||||
color: #000;
|
||||
}
|
||||
:global(body.dark .fa.fa-expand, body.dark .fa.fa-compress) {
|
||||
color: #e9e9e9;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import Prism from 'prismjs';
|
||||
import beautify from "js-beautify";
|
||||
export let title = "";
|
||||
export let code = ``;
|
||||
export let file = "";
|
||||
|
||||
function highlight(code) {
|
||||
const beautified = beautify.js(code, {
|
||||
indent_size: 4,
|
||||
space_in_empty_paren: true,
|
||||
});
|
||||
const highlighted = Prism.highlight(
|
||||
beautified,
|
||||
Prism.languages.javascript
|
||||
);
|
||||
return highlighted;
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (file) {
|
||||
code = await (await fetch(file)).text();
|
||||
title = file.split("/")[file.split("/").length - 1];
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="code-wrapper">
|
||||
{#if title}
|
||||
<p class="title">{title}</p>
|
||||
<hr>
|
||||
{/if}
|
||||
{#each code.split("\n") as line,i}
|
||||
<div class="line">{#if title}<span class="line-count" style="width: {Math.floor(code.split("\n").length.toString().length) * 10}px;">{i + 1}</span>{/if} <code class="code-line language-javascript">{@html highlight(line)}</code></div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.code-line {
|
||||
border-radius: 0;
|
||||
white-space: pre;
|
||||
border: none;
|
||||
}
|
||||
.line-count {
|
||||
font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;
|
||||
color: lightgray;
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
display: inline-block;
|
||||
user-select: none;
|
||||
}
|
||||
:global(body.dark) .line-count {
|
||||
color: gray;
|
||||
}
|
||||
.line {
|
||||
display: block;
|
||||
}
|
||||
.title {
|
||||
margin: 0;
|
||||
padding: .75rem;
|
||||
font-size: 90%;
|
||||
}
|
||||
hr {
|
||||
width: calc(100% + 17px);
|
||||
position: relative;
|
||||
left: -10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.code-wrapper {
|
||||
padding: 10px;
|
||||
background: #f5f2f0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
:global(body.dark) .code-wrapper {
|
||||
background: #2d2d2d;
|
||||
}
|
||||
</style>
|
||||
455
src/lib/MenuModals/CreateBlock.svelte
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
<script>
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import EventManager from "../../resources/events";
|
||||
import ModalScript from "./createblock.js";
|
||||
import ColorUtil from "./color.js";
|
||||
|
||||
import Blockly from "blockly/core";
|
||||
const Theme = Blockly.Theme.defineTheme("MakeABlockTheme", {
|
||||
base: Blockly.Themes.Classic,
|
||||
blockStyles: {
|
||||
core_makeablock_test: {
|
||||
colourPrimary: "#ff0000",
|
||||
colourSecondary: "#00ff00",
|
||||
colourTertiary: "#0000ff",
|
||||
},
|
||||
},
|
||||
fontStyle: {
|
||||
family: '"Helvetica Neue", Helvetica, Arial, sans-serif',
|
||||
weight: "600",
|
||||
size: 12,
|
||||
},
|
||||
startHats: true,
|
||||
});
|
||||
|
||||
import En from "blockly/msg/en";
|
||||
import "blockly/blocks";
|
||||
|
||||
import BlocklyComponent from "svelte-blockly";
|
||||
|
||||
const en = {
|
||||
rtl: false,
|
||||
msg: {
|
||||
...En,
|
||||
},
|
||||
};
|
||||
|
||||
const config = {
|
||||
scrollbars: true,
|
||||
disable: false,
|
||||
theme: Theme,
|
||||
renderer: "custom_renderer",
|
||||
grid: {
|
||||
spacing: 25,
|
||||
length: 3,
|
||||
colour: "#00000011",
|
||||
snap: false,
|
||||
},
|
||||
zoom: {
|
||||
controls: true,
|
||||
wheel: false,
|
||||
startScale: 1.2,
|
||||
maxScale: 4,
|
||||
minScale: 0.25,
|
||||
scaleSpeed: 1.1,
|
||||
},
|
||||
move: {
|
||||
scrollbars: {
|
||||
horizontal: true,
|
||||
vertical: true,
|
||||
},
|
||||
drag: true,
|
||||
wheel: true,
|
||||
},
|
||||
};
|
||||
|
||||
let workspace;
|
||||
const defaultWorkspaceXML = `<xml><block type="core_builderblock" /></xml>`;
|
||||
|
||||
const validation = {
|
||||
id: (id) => {
|
||||
return !String(id).match(/[^a-zA-Z0-9_]+/gim);
|
||||
},
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
EventManager.allowAttachment();
|
||||
EventManager.on(EventManager.EVENT_THEME_CHANGED, () => {
|
||||
workspace.refreshTheme();
|
||||
});
|
||||
});
|
||||
|
||||
export let color1 = "#ff0000";
|
||||
export let color2 = "#00ff00";
|
||||
export let color3 = "#0000ff";
|
||||
let visible = false;
|
||||
|
||||
function generateColor3(color1) {
|
||||
const rgb = ColorUtil.hexToRGB(color1);
|
||||
const r = Math.max(0, rgb.r - 51);
|
||||
const g = Math.max(0, rgb.g - 51);
|
||||
const b = Math.max(0, rgb.b - 51);
|
||||
return ColorUtil.rgbToHex(r, g, b);
|
||||
}
|
||||
function getBlockStyle() {
|
||||
return {
|
||||
colourPrimary: color1,
|
||||
colourSecondary: color2,
|
||||
colourTertiary: color3 ? color3 : generateColor3(color1),
|
||||
};
|
||||
}
|
||||
|
||||
function getDefaultState() {
|
||||
return {
|
||||
block: {
|
||||
id: "",
|
||||
},
|
||||
};
|
||||
}
|
||||
const dispatch = createEventDispatcher();
|
||||
let state = getDefaultState();
|
||||
|
||||
function event() {
|
||||
// validate all
|
||||
if (!state.block.id || !validation.id(state.block.id)) {
|
||||
return alert("Block ID is either invalid or not set.");
|
||||
}
|
||||
// set state
|
||||
dispatch("completed", state);
|
||||
visible = false;
|
||||
}
|
||||
function cancel() {
|
||||
dispatch("cancel");
|
||||
visible = false;
|
||||
}
|
||||
|
||||
ModalScript.onopened = () => {
|
||||
// create block style
|
||||
Theme.blockStyles["core_makeablock_colors"] = getBlockStyle();
|
||||
console.log(Theme);
|
||||
workspace.refreshTheme();
|
||||
|
||||
visible = true;
|
||||
state = getDefaultState();
|
||||
|
||||
// reset & load
|
||||
workspace.clear();
|
||||
const newXml = Blockly.utils.xml.textToDom(defaultWorkspaceXML);
|
||||
Blockly.Xml.domToWorkspace(newXml, workspace);
|
||||
|
||||
// modify block
|
||||
const block = workspace.getAllBlocks()[0];
|
||||
block.setStyle("core_makeablock_colors");
|
||||
block.setEditable(false);
|
||||
block.setMovable(false);
|
||||
block.setDeletable(false);
|
||||
console.log(block);
|
||||
|
||||
// center
|
||||
workspace.centerOnBlock(block.id, true);
|
||||
setTimeout(() => {
|
||||
workspace.centerOnBlock(block.id, true);
|
||||
block.setStyle("core_makeablock_colors");
|
||||
}, 50);
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="bg" style={visible ? "" : "display:none"}>
|
||||
<div class="modal">
|
||||
<div class="modal-title">
|
||||
<p>Make a Block</p>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div class="blockly-wrapper">
|
||||
<BlocklyComponent {config} locale={en} bind:workspace />
|
||||
</div>
|
||||
<div class="button-space">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Block ID (ex: numberIsWithinNumbers)"
|
||||
class="block-id"
|
||||
data-invalid={!validation.id(state.block.id)}
|
||||
bind:value={state.block.id}
|
||||
/>
|
||||
{#if !validation.id(state.block.id)}
|
||||
<p class="block-id-warning">
|
||||
Block ID can only contain letters A-Z, numbers 0-9, and
|
||||
the _ symbol.
|
||||
</p>
|
||||
{:else}
|
||||
<br />
|
||||
{/if}
|
||||
<div
|
||||
style="display: flex; flex-direction: row; justify-content: center;"
|
||||
>
|
||||
<button class="block-addition">
|
||||
Add Text label
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Label"
|
||||
src="/images/blockBuilder/block_label.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Text input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Text input"
|
||||
src="/images/blockBuilder/block_input_text.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Number input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Number input"
|
||||
src="/images/blockBuilder/block_input_number.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Boolean input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Boolean input"
|
||||
src="/images/blockBuilder/block_boolean.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Color input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Color input"
|
||||
src="/images/blockBuilder/block_input_color.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style="display: flex; flex-direction: row; justify-content: center;"
|
||||
>
|
||||
<details>
|
||||
<summary>Advanced Inputs</summary>
|
||||
<button class="block-addition">
|
||||
Add Angle input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Angle input"
|
||||
src="/images/blockBuilder/block_input_angle.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Matrix input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Matrix input"
|
||||
src="/images/blockBuilder/block_input_matrix.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Note input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Note input"
|
||||
src="/images/blockBuilder/block_input_note.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Image label
|
||||
<div style="height:4px" />
|
||||
<!-- svelte-ignore a11y-img-redundant-alt -->
|
||||
<img
|
||||
alt="Image Label"
|
||||
src="/images/blockBuilder/block_label_image.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Add Empty input
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Empty Input"
|
||||
src="/images/blockBuilder/block_empty.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
<button class="block-addition">
|
||||
Use Enum Name
|
||||
<div style="height:4px" />
|
||||
<img
|
||||
alt="Empty"
|
||||
src="/images/blockBuilder/block_label_none.svg"
|
||||
height={50}
|
||||
/>
|
||||
</button>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="button-cancel" on:click={cancel}>Cancel</button>
|
||||
<div style="margin-left:6px" />
|
||||
<button class="button-accept" on:click={event}>OK</button>
|
||||
<div style="margin-left:24px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.button-cancel {
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
background: white;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.button-accept {
|
||||
border: 1px solid #ff4b4b;
|
||||
background: #ff4b4b;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.blockly-wrapper {
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
}
|
||||
.button-space {
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ff4b4bb0;
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal {
|
||||
width: 60%;
|
||||
height: 80%;
|
||||
outline: 4px solid hsla(0, 100%, 100%, 0.25);
|
||||
border-radius: 0.5rem;
|
||||
background: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(body.dark) .bg {
|
||||
background-color: #333333b0;
|
||||
}
|
||||
:global(body.dark) .modal {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
width: 100%;
|
||||
height: 7%;
|
||||
background: #ff4b4b;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
:global(body.dark) .modal-title {
|
||||
background-color: #333;
|
||||
}
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
height: 83%;
|
||||
overflow: auto;
|
||||
}
|
||||
.modal-buttons {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.block-id {
|
||||
width: 90%;
|
||||
height: 24px;
|
||||
margin-top: 4px;
|
||||
margin-left: 5%;
|
||||
border-radius: 1024px;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
outline: 0px solid #ff4b4b44;
|
||||
transition: 0.25s linear;
|
||||
}
|
||||
.block-id:focus,
|
||||
.block-id:active {
|
||||
border: 1px solid #ff4b4b;
|
||||
outline: 4px solid #ff4b4b44;
|
||||
transition: 0.25s linear;
|
||||
}
|
||||
:global(body.dark) .block-id {
|
||||
background: transparent;
|
||||
border-color: rgba(255, 255, 255, 0.7);
|
||||
color: white;
|
||||
}
|
||||
.block-id[data-invalid="true"] {
|
||||
background-color: #ffabab;
|
||||
text-decoration: red underline;
|
||||
}
|
||||
:global(body.dark) .block-id[data-invalid="true"] {
|
||||
background-color: #9b0000 !important;
|
||||
text-decoration: red underline;
|
||||
}
|
||||
|
||||
.block-id-warning {
|
||||
width: 100%;
|
||||
margin-block: 0;
|
||||
margin: 8px 0px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.block-addition {
|
||||
background: transparent;
|
||||
font-weight: bold;
|
||||
margin: 5px;
|
||||
padding: 8px 32px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
:global(body.dark) .block-addition {
|
||||
color: white;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.block-addition:focus,
|
||||
.block-addition:hover {
|
||||
border-color: #ff4b4b !important;
|
||||
}
|
||||
.block-addition:active {
|
||||
border-color: black !important;
|
||||
}
|
||||
:global(body.dark) .block-addition:active {
|
||||
border-color: rgb(114, 114, 114) !important;
|
||||
}
|
||||
</style>
|
||||
311
src/lib/MenuModals/ExtensionColors.svelte
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import ColorUtil from "./color.js";
|
||||
|
||||
import colorExample from "./extensionColorExample.svg?raw";
|
||||
|
||||
export let color1 = "#ff0000";
|
||||
export let color2 = "#00ff00";
|
||||
export let color3 = "#0000ff";
|
||||
|
||||
let color3Included = false;
|
||||
export let tbShow = true;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function event() {
|
||||
console.log(color3Included);
|
||||
if (!color3Included) {
|
||||
color3 = "";
|
||||
}
|
||||
if (color3Included && !color3) {
|
||||
color3 = "#000000";
|
||||
}
|
||||
dispatch("completed", {
|
||||
color1,
|
||||
color2,
|
||||
color3,
|
||||
tbShow
|
||||
});
|
||||
}
|
||||
function cancel() {
|
||||
dispatch("cancel");
|
||||
}
|
||||
|
||||
function getExampleData(color1, color2, color3, color3Included) {
|
||||
const tokens = ["[{{COLOR1}}]", "[{{COLOR2}}]", "[{{COLOR3}}]"];
|
||||
if (color3Included && !color3) {
|
||||
color3 = "#000000";
|
||||
}
|
||||
if (!color3 || !color3Included) {
|
||||
const rgb = ColorUtil.hexToRGB(color1);
|
||||
const r = Math.max(0, rgb.r - 51);
|
||||
const g = Math.max(0, rgb.g - 51);
|
||||
const b = Math.max(0, rgb.b - 51);
|
||||
color3 = ColorUtil.rgbToHex(r, g, b);
|
||||
}
|
||||
return colorExample
|
||||
.replaceAll(tokens[0], color1)
|
||||
.replaceAll(tokens[1], color2)
|
||||
.replaceAll(tokens[2], color3);
|
||||
}
|
||||
function getExampleURL(...args) {
|
||||
const data = getExampleData(...args);
|
||||
return "data:image/svg+xml," + encodeURIComponent(data);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="bg">
|
||||
<div class="modal">
|
||||
<div class="modal-title">
|
||||
<p>Colors</p>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div
|
||||
style="display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%"
|
||||
>
|
||||
<p>Choose the colors used in your extension's blocks & menu.</p>
|
||||
<div
|
||||
style="display:flex;flex-direction:row;align-items:center;"
|
||||
>
|
||||
<label>
|
||||
Primary
|
||||
<input type="color" bind:value={color1} />
|
||||
</label>
|
||||
<div style="margin-left:6px" />
|
||||
<label>
|
||||
Secondary
|
||||
<input type="color" bind:value={color2} />
|
||||
</label>
|
||||
<div style="margin-left:6px" />
|
||||
<label>
|
||||
Teritary
|
||||
<input type="color" bind:value={color3} />
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;flex-direction:row;align-items:center;"
|
||||
>
|
||||
<label>
|
||||
Include Teritary Color
|
||||
<input type="checkbox" bind:checked={color3Included} />
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;flex-direction:row;align-items:center;"
|
||||
>
|
||||
<label>
|
||||
TurboBuilder Indicator (PenguinMod Experimental Feature)
|
||||
<input type="checkbox" bind:checked={tbShow} />
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;flex-direction:row;align-items:center;"
|
||||
>
|
||||
<div class="extensionMenuPreview">
|
||||
<div style="text-align: center;">
|
||||
<div
|
||||
class="extensionBubbleIcon"
|
||||
style={`background: ${color1}; border-color: ${color2}`}
|
||||
>
|
||||
{#if tbShow}
|
||||
<img
|
||||
class="tbBubbleIcon"
|
||||
src="favicon.png"
|
||||
alt="TurboBuilder"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="extensionBubbleName">Extension</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img
|
||||
alt="Color preview"
|
||||
src={getExampleURL(
|
||||
color1,
|
||||
color2,
|
||||
color3,
|
||||
color3Included
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="button-cancel" on:click={cancel}>Cancel</button>
|
||||
<div style="margin-left:6px" />
|
||||
<button class="button-accept" on:click={event}>OK</button>
|
||||
<div style="margin-left:24px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.button-cancel {
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
background: white;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.button-accept {
|
||||
border: 1px solid #ff4b4b;
|
||||
background: #ff4b4b;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
font-size: 0.625rem;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
input[type="color"] {
|
||||
margin-left: 3px;
|
||||
}
|
||||
img {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* color picker */
|
||||
input[type="color"] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="color"]::-webkit-color-swatch {
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
input[type="color"]::-moz-color-swatch {
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
:global(body.dark) input[type="color"]::-webkit-color-swatch {
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
:global(body.dark) input[type="color"]::-moz-color-swatch {
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ff4b4bb0;
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal {
|
||||
width: 60%;
|
||||
height: 50%;
|
||||
outline: 4px solid hsla(0, 100%, 100%, 0.25);
|
||||
border-radius: 0.5rem;
|
||||
background: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(body.dark) .bg {
|
||||
background-color: #333333b0;
|
||||
}
|
||||
:global(body.dark) .modal {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
background: #ff4b4b;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
:global(body.dark) .modal-title {
|
||||
background-color: #333;
|
||||
}
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
height: 75%;
|
||||
overflow: auto;
|
||||
}
|
||||
.modal-buttons {
|
||||
width: 100%;
|
||||
height: 15%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.extensionMenuPreview {
|
||||
width: 60px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: #575e75;
|
||||
user-select: none;
|
||||
}
|
||||
.extensionMenuPreview:hover {
|
||||
color: #4c97ff !important;
|
||||
}
|
||||
.extensionMenuPreview:focus,
|
||||
.extensionMenuPreview:active {
|
||||
background-color: #e9eef2;
|
||||
}
|
||||
|
||||
.tbBubbleIcon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #0006;
|
||||
backdrop-filter: blur(2px);
|
||||
border-radius: 8px;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
}
|
||||
|
||||
:global(body.dark) .extensionMenuPreview {
|
||||
color: #ccc;
|
||||
}
|
||||
:global(body.dark) .extensionMenuPreview:focus,
|
||||
:global(body.dark) .extensionMenuPreview:active {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
.extensionBubbleIcon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-size: 100%;
|
||||
border-radius: 100%;
|
||||
margin: 0 auto 0.125rem;
|
||||
border: 1px rgba(0, 0, 0, 0.2) solid;
|
||||
position: relative;
|
||||
}
|
||||
.extensionBubbleName {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import fileDialog from "../../resources/fileDialog";
|
||||
|
||||
let URL = "";
|
||||
let Text = "";
|
||||
let File = "";
|
||||
let selected = "URL";
|
||||
let btnText = "No file selected.";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function event() {
|
||||
dispatch("completed", {
|
||||
selected,
|
||||
URL,
|
||||
Text,
|
||||
File,
|
||||
});
|
||||
}
|
||||
function cancel() {
|
||||
dispatch("cancel");
|
||||
}
|
||||
function file() {
|
||||
fileDialog({ accept: ".js" }).then((files) => {
|
||||
if (!files) return;
|
||||
File = files[0];
|
||||
btnText = "Selected: " + File.name;
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="bg">
|
||||
<div class="modal">
|
||||
<div class="modal-title">
|
||||
<p>Load Custom Extension</p>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div class="tabs">
|
||||
<div class="tab {(selected == "URL" ? "selected" : "")}" on:click={() => {selected = "URL"}}>URL</div>
|
||||
<div class="tab {(selected == "Files" ? "selected" : "")}" on:click={() => {selected = "Files"}}>Files</div>
|
||||
<div class="tab {(selected == "Text" ? "selected" : "")}" on:click={() => {selected = "Text"}}>Text</div>
|
||||
</div>
|
||||
{#if selected == "URL"}
|
||||
<p>Enter the extension's URL:</p>
|
||||
<input
|
||||
class="extension-import-input"
|
||||
type="text"
|
||||
placeholder="https://eaglerforge-builder.vercel.app/extensions/..."
|
||||
style=""
|
||||
bind:value={URL}
|
||||
/>
|
||||
{:else if selected == "Files"}
|
||||
<p>Select or drop an extension's JavaScript file:</p>
|
||||
<button class="file-selector-button" on:click={file}>{btnText}</button>
|
||||
{:else if selected == "Text"}
|
||||
<p>Paste the extension's JavaScript source code:</p>
|
||||
<textarea
|
||||
class="extension-import-input"
|
||||
type="text"
|
||||
placeholder="{`class Extension {
|
||||
// ...
|
||||
}
|
||||
EaglerBuilder.extensions.register(new Extension());`}"
|
||||
style="resize: vertical;height:100px;"
|
||||
bind:value={Text}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="button-cancel" on:click={cancel}>Cancel</button>
|
||||
<div style="margin-left:6px" />
|
||||
<button class="button-accept" on:click={event}>Load</button>
|
||||
<div style="margin-left:24px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.button-cancel {
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
background: white;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.button-accept {
|
||||
border: 1px solid rgb(86, 114, 205);
|
||||
background: rgb(86, 114, 205);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.file-selector-button {
|
||||
padding: 0.35rem 1.65rem;
|
||||
font-size: 1rem;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
color: black;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border: 3px dashed rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.file-selector-button:focus,
|
||||
.file-selector-button:hover,
|
||||
.file-selector-button:active {
|
||||
background: white;
|
||||
}
|
||||
|
||||
:global(body.dark) .file-selector-button {
|
||||
color: white;
|
||||
border-color: #2e2e2e;
|
||||
}
|
||||
:global(body.dark) .file-selector-button:focus,
|
||||
:global(body.dark) .file-selector-button:hover,
|
||||
:global(body.dark) .file-selector-button:active {
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab {
|
||||
height: 40px;
|
||||
width: 100px;
|
||||
border-bottom: 5px hsla(215, 50%, 90%, 1) solid;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
transition-duration: 0.25s;
|
||||
}
|
||||
|
||||
:global(body.dark) .tab {
|
||||
border-bottom: 5px #2e2e2e solid;
|
||||
}
|
||||
|
||||
.tab.selected, :global(body.dark) .tab.selected {
|
||||
border-bottom: 5px rgb(86, 114, 205) solid;
|
||||
}
|
||||
|
||||
:global(body.dark) input[type="text"], :global(body.dark) textarea {
|
||||
background: inherit;
|
||||
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
color: white;
|
||||
}
|
||||
:global(body.dark) input[type="text"]:hover, :global(body.dark) textarea:hover {
|
||||
background: inherit;
|
||||
border: 1px solid dodgerblue;
|
||||
}
|
||||
.extension-import-input {
|
||||
font-size: 20px;
|
||||
border-radius: 6px;
|
||||
outline: 1px dashed rgba(0, 0, 0, 0.15);
|
||||
border: 0;
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem;
|
||||
transition: 0.25s;
|
||||
margin-left:4px;
|
||||
margin-right:4px;
|
||||
margin-bottom:4px;
|
||||
width:calc(100% - 25px);
|
||||
}
|
||||
.extension-import-input:hover {
|
||||
transition: 0.25s;
|
||||
}
|
||||
.extension-import-input:active,
|
||||
.extension-import-input:focus {
|
||||
box-shadow: 0 0 0 calc(0.5rem * 0.5) hsla(0, 100%, 100%, 0.25);
|
||||
transition: 0.25s;
|
||||
}
|
||||
.extension-import-input:active,
|
||||
.extension-import-input:focus {
|
||||
box-shadow: 0 0 0 calc(0.5rem * 0.5) hsla(0, 100%, 100%, 0.25);
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(86, 114, 205, 0.69019607843);
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal {
|
||||
width: 60%;
|
||||
height: 50%;
|
||||
outline: 4px solid hsla(0, 100%, 100%, 0.25);
|
||||
border-radius: 0.5rem;
|
||||
background: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(body.dark) .bg {
|
||||
background-color: #333333b0;
|
||||
}
|
||||
:global(body.dark) .modal {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
background: rgb(86, 114, 205);
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
:global(body.dark) .modal-title {
|
||||
background-color: #333;
|
||||
}
|
||||
.modal-content {
|
||||
width: calc(100% - 50px);
|
||||
height: 75%;
|
||||
overflow: auto;
|
||||
padding: 25px;
|
||||
}
|
||||
.modal-buttons {
|
||||
width: 100%;
|
||||
height: 15%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: right;
|
||||
}
|
||||
</style>
|
||||
120
src/lib/MenuModals/color.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
class Color {
|
||||
static hexToRGB(h) {
|
||||
let r = 0, g = 0, b = 0;
|
||||
|
||||
// 3 digits
|
||||
if (h.length == 4) {
|
||||
r = "0x" + h[1] + h[1];
|
||||
g = "0x" + h[2] + h[2];
|
||||
b = "0x" + h[3] + h[3];
|
||||
|
||||
// 6 digits
|
||||
} else if (h.length == 7) {
|
||||
r = "0x" + h[1] + h[2];
|
||||
g = "0x" + h[3] + h[4];
|
||||
b = "0x" + h[5] + h[6];
|
||||
}
|
||||
|
||||
return { r: +r, g: +g, b: +b };
|
||||
}
|
||||
static rgbToHex(r, g, b) {
|
||||
r = r.toString(16);
|
||||
g = g.toString(16);
|
||||
b = b.toString(16);
|
||||
|
||||
if (r.length == 1)
|
||||
r = "0" + r;
|
||||
if (g.length == 1)
|
||||
g = "0" + g;
|
||||
if (b.length == 1)
|
||||
b = "0" + b;
|
||||
|
||||
return "#" + r + g + b;
|
||||
}
|
||||
|
||||
static hexToHSL(H) {
|
||||
// Convert hex to RGB first
|
||||
let r = 0, g = 0, b = 0;
|
||||
if (H.length == 4) {
|
||||
r = "0x" + H[1] + H[1];
|
||||
g = "0x" + H[2] + H[2];
|
||||
b = "0x" + H[3] + H[3];
|
||||
} else if (H.length == 7) {
|
||||
r = "0x" + H[1] + H[2];
|
||||
g = "0x" + H[3] + H[4];
|
||||
b = "0x" + H[5] + H[6];
|
||||
}
|
||||
// Then to HSL
|
||||
r /= 255;
|
||||
g /= 255;
|
||||
b /= 255;
|
||||
let cmin = Math.min(r, g, b),
|
||||
cmax = Math.max(r, g, b),
|
||||
delta = cmax - cmin,
|
||||
h = 0,
|
||||
s = 0,
|
||||
l = 0;
|
||||
|
||||
if (delta == 0)
|
||||
h = 0;
|
||||
else if (cmax == r)
|
||||
h = ((g - b) / delta) % 6;
|
||||
else if (cmax == g)
|
||||
h = (b - r) / delta + 2;
|
||||
else
|
||||
h = (r - g) / delta + 4;
|
||||
|
||||
h = Math.round(h * 60);
|
||||
|
||||
if (h < 0)
|
||||
h += 360;
|
||||
|
||||
l = (cmax + cmin) / 2;
|
||||
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
||||
s = +(s * 100).toFixed(1);
|
||||
l = +(l * 100).toFixed(1);
|
||||
|
||||
return { h, s, l };
|
||||
}
|
||||
static hslToHex(h, s, l) {
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
|
||||
let c = (1 - Math.abs(2 * l - 1)) * s,
|
||||
x = c * (1 - Math.abs((h / 60) % 2 - 1)),
|
||||
m = l - c / 2,
|
||||
r = 0,
|
||||
g = 0,
|
||||
b = 0;
|
||||
|
||||
if (0 <= h && h < 60) {
|
||||
r = c; g = x; b = 0;
|
||||
} else if (60 <= h && h < 120) {
|
||||
r = x; g = c; b = 0;
|
||||
} else if (120 <= h && h < 180) {
|
||||
r = 0; g = c; b = x;
|
||||
} else if (180 <= h && h < 240) {
|
||||
r = 0; g = x; b = c;
|
||||
} else if (240 <= h && h < 300) {
|
||||
r = x; g = 0; b = c;
|
||||
} else if (300 <= h && h < 360) {
|
||||
r = c; g = 0; b = x;
|
||||
}
|
||||
// Having obtained RGB, convert channels to hex
|
||||
r = Math.round((r + m) * 255).toString(16);
|
||||
g = Math.round((g + m) * 255).toString(16);
|
||||
b = Math.round((b + m) * 255).toString(16);
|
||||
|
||||
// Prepend 0s, if necessary
|
||||
if (r.length == 1)
|
||||
r = "0" + r;
|
||||
if (g.length == 1)
|
||||
g = "0" + g;
|
||||
if (b.length == 1)
|
||||
b = "0" + b;
|
||||
|
||||
return "#" + r + g + b;
|
||||
}
|
||||
}
|
||||
|
||||
export default Color;
|
||||
8
src/lib/MenuModals/createblock.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
class ModalScript {
|
||||
static onopened = () => { };
|
||||
static open = () => {
|
||||
ModalScript.onopened();
|
||||
};
|
||||
}
|
||||
|
||||
export default ModalScript;
|
||||
72
src/lib/MenuModals/extensionColorExample.svg
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="610" height="47"
|
||||
viewBox="60 63 600 47">
|
||||
<style xmlns="http://www.w3.org/1999/xhtml">
|
||||
.blocklyText {
|
||||
fill: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.blocklyNonEditableText>
|
||||
text,
|
||||
.blocklyEditableText>
|
||||
|
||||
text {
|
||||
fill: #575E75;
|
||||
}
|
||||
|
||||
.blocklyDropdownText {
|
||||
fill: #fff !important;
|
||||
}
|
||||
</style>
|
||||
<g class="blocklyBlockCanvas" transform="translate(50.25925925925878,-245.1111111111107) ">
|
||||
<g data-id="g](S2C.?x|-b4JmCKOwt" class="blocklyDraggable" data-shapes="reporter round"
|
||||
data-category="Color Example" transform="translate(7.55555555555577,311.555555555557)">
|
||||
<path class="blocklyPath blocklyBlockBackground" stroke="[{{COLOR3}}]" fill="[{{COLOR1}}]" fill-opacity="1"
|
||||
d="m 0,0 m 20,0 H 583.2361068725586 a 20 20 0 0 1 0 40 H 20 a 20 20 0 0 1 0 -40 z" />
|
||||
<g data-id="-M:/l`Z%A[/Px0zD=s3z" data-argument-type="text" data-shapes="argument round"
|
||||
transform="translate(45.810184478759766,4)">
|
||||
<path class="blocklyPath blocklyBlockBackground" stroke="[{{COLOR3}}]" fill="#FFFFFF" fill-opacity="1"
|
||||
d="m 0,0 m 16,0 H 31.810184478759766 a 16 16 0 0 1 0 32 H 16 a 16 16 0 0 1 0 -32 z" />
|
||||
<g class="blocklyEditableText" transform="translate(8, 0) " style="cursor: text;"><text
|
||||
class="blocklyText" x="15.905092239379883" y="18" dominant-baseline="middle" dy="0"
|
||||
text-anchor="middle">abc</text></g>
|
||||
</g>
|
||||
<g data-id="Mx?Tr{J@YX*x;2raXMtA" data-argument-type="dropdown" data-shapes="argument round"
|
||||
transform="translate(310.6574020385742,4)">
|
||||
<path class="blocklyPath blocklyBlockBackground" stroke="[{{COLOR3}}]" fill="[{{COLOR2}}]" fill-opacity="1"
|
||||
d="m 0,0 m 16,0 H 69.58796310424805 a 16 16 0 0 1 0 32 H 16 a 16 16 0 0 1 0 -32 z" />
|
||||
<g class="blocklyEditableText" transform="translate(8, 0) " style="cursor: default;"><text
|
||||
class="blocklyText blocklyDropdownText" x="24.793981552124023" y="18" dominant-baseline="middle"
|
||||
dy="0" text-anchor="middle">item 1</text>
|
||||
<image height="12px" width="12px" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xlink:href="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaGVpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLWFycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuNDEsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTDAuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNzFDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMCwxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNzlhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYzAuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMzdBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="
|
||||
transform="translate(53.58796310424805,11)" />
|
||||
</g>
|
||||
</g><text class="blocklyText" y="2" text-anchor="middle" dominant-baseline="middle" dy="0"
|
||||
x="12.905092239379883" transform="translate(12, 20) ">text</text>
|
||||
<path class="blocklyPath" style="visibility: hidden" d="" fill="[{{COLOR3}}]" /><text class="blocklyText" y="2"
|
||||
text-anchor="middle" dominant-baseline="middle" dy="0" x="28.483795166015625"
|
||||
transform="translate(101.62036895751953, 20) ">boolean</text>
|
||||
<path class="blocklyPath" style="visibility: visible"
|
||||
d="M 16,0 h 16 l 16,16 l -16,16 h -16 l -16,-16 l 16,-16 z" fill="[{{COLOR3}}]"
|
||||
transform="translate(166.58795928955078,4)" data-argument-type="boolean" /><text class="blocklyText"
|
||||
y="2" text-anchor="middle" dominant-baseline="middle" dy="0" x="40.03472137451172"
|
||||
transform="translate(222.58795928955078, 20) ">open menu</text>
|
||||
<path class="blocklyPath" style="visibility: hidden" d="" fill="[{{COLOR3}}]" /><text class="blocklyText" y="2"
|
||||
text-anchor="middle" dominant-baseline="middle" dy="0" x="46.70138931274414"
|
||||
transform="translate(404.24536514282227, 20) ">square menu</text>
|
||||
<g data-argument-type="dropdown" class="blocklyEditableText" transform="translate(505.64814376831055, 4) "
|
||||
style="cursor: default;">
|
||||
<rect rx="4" ry="4" x="0" y="0" width="85.58796310424805" height="32" stroke="[{{COLOR3}}]" fill="[{{COLOR1}}]"
|
||||
class="blocklyBlockBackground" fill-opacity="1" /><text class="blocklyText blocklyDropdownText"
|
||||
x="32.79398155212402" y="18" dominant-baseline="middle" dy="0" text-anchor="middle">item 1</text>
|
||||
<image height="12px" width="12px" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xlink:href="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaGVpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLWFycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuNDEsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTDAuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNzFDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMCwxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNzlhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYzAuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMzdBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="
|
||||
transform="translate(61.58796310424805,11)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
// Components
|
||||
import Divider from "$lib/NavigationBar/Divider.svelte";
|
||||
import Button from "$lib/NavigationBar/Button.svelte";
|
||||
|
||||
const switchTheme = () => {
|
||||
const id = "tb:theme";
|
||||
|
|
@ -17,10 +16,6 @@
|
|||
currentData === "dark" ? "light" : "dark"
|
||||
);
|
||||
};
|
||||
|
||||
function link(link) {
|
||||
window.location.href = link;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="nav">
|
||||
|
|
@ -34,9 +29,6 @@
|
|||
<img src="/images/theme_switcher.svg" alt="Theme Switcher" />
|
||||
</button>
|
||||
<Divider />
|
||||
<Button on:click={() => link("/")}>Editor</Button>
|
||||
<Button on:click={() => link("/docs")}>Docs</Button>
|
||||
<Divider />
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
|
|
@ -56,8 +48,7 @@
|
|||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
background: rgb(86, 114, 205);
|
||||
z-index: 99;
|
||||
background: rgb(86, 114, 205)
|
||||
}
|
||||
.logo-margin {
|
||||
margin: 0 6px;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@
|
|||
<block type="sound_startsound" />
|
||||
</category>
|
||||
<category name="Sensing" colour="#5CB1D6">
|
||||
<!--
|
||||
<block type="sensing_keypress" />
|
||||
<sep gap="48"></sep>
|
||||
-->
|
||||
<block type="sensing_alert" />
|
||||
<block type="sensing_prompt" />
|
||||
<block type="sensing_confirm" />
|
||||
|
|
@ -100,6 +104,7 @@
|
|||
<sep gap="48"></sep>
|
||||
<block type="operators_join" />
|
||||
<block type="operators_letter" />
|
||||
<!--<block type="operators_addblock" />-->
|
||||
</category>
|
||||
<category name="Conversions" colour="#8BC059">
|
||||
<block type="conversions_tonumber" />
|
||||
|
|
@ -134,6 +139,13 @@
|
|||
<block type="json_objectvalues" />
|
||||
</category>
|
||||
<sep></sep>
|
||||
<!--<category name="Blocks" colour="#FF6680">
|
||||
<block type="blocks_create" />
|
||||
<block type="blocks_input" />
|
||||
<sep gap="48"></sep>
|
||||
<block type="blocks_get" />
|
||||
<block type="blocks_return" />
|
||||
</category>-->
|
||||
<category name="Functions" colour="#5531D6">
|
||||
<block type="functions_create">
|
||||
<statement name="FUNC">
|
||||
|
|
@ -225,5 +237,4 @@
|
|||
<sep gap="48"></sep>
|
||||
<block type="interface_currentscreen"/>
|
||||
</category>
|
||||
<sep></sep>
|
||||
</xml>
|
||||
|
|
@ -208,14 +208,10 @@ const keyBoard = [
|
|||
["F12", "123"],
|
||||
];
|
||||
|
||||
try {
|
||||
Blockly.Extensions.register('single_character_validation', function() {
|
||||
this.getField('KEY').setValidator(function(newValue) {
|
||||
return newValue.substring(Math.max(newValue.length - 1, 0),newValue.length);
|
||||
});
|
||||
});
|
||||
} catch {
|
||||
console.log("Reload")
|
||||
}
|
||||
|
||||
export default register;
|
||||
|
|
|
|||
|
|
@ -8,15 +8,12 @@ class Compiler {
|
|||
* @param {object} imageStates
|
||||
* @returns {string} Generated code.
|
||||
*/
|
||||
compile(workspace) {
|
||||
compile(workspace, extensionMetadata, imageStates) {
|
||||
const code = javascriptGenerator.workspaceToCode(workspace);
|
||||
let start = '';
|
||||
if (code.indexOf('ModAPI.player') > -1) {
|
||||
start+= "ModAPI.require('player');";
|
||||
}
|
||||
if (code.indexOf('ModAPI.settings') > -1) {
|
||||
start+= "ModAPI.require('settings');";
|
||||
}
|
||||
if (code.indexOf('sendData(') > -1) {
|
||||
start+= `function sendData(message,url) {
|
||||
var request = new XMLHttpRequest();
|
||||
|
|
@ -58,6 +55,39 @@ class Compiler {
|
|||
end+= 'onload();';
|
||||
}
|
||||
const footerCode = end;
|
||||
|
||||
if (imageStates) {
|
||||
if (imageStates.icon.image) {
|
||||
// add icon uri
|
||||
const url = imageStates.icon.image;
|
||||
classRegistry.extensionInfo.blockIconURI = url;
|
||||
}
|
||||
if (imageStates.menuicon.image) {
|
||||
// add icon uri
|
||||
const url = imageStates.menuicon.image;
|
||||
classRegistry.extensionInfo.menuIconURI = url;
|
||||
}
|
||||
}
|
||||
if (extensionMetadata) {
|
||||
classRegistry.extensionInfo.id = extensionMetadata.id;
|
||||
classRegistry.extensionInfo.name = extensionMetadata.name;
|
||||
if (extensionMetadata.docsURL) {
|
||||
classRegistry.extensionInfo.docsURI = extensionMetadata.docsURL;
|
||||
}
|
||||
if (extensionMetadata.color1) {
|
||||
classRegistry.extensionInfo.color1 = extensionMetadata.color1;
|
||||
}
|
||||
if (extensionMetadata.color2) {
|
||||
classRegistry.extensionInfo.color2 = extensionMetadata.color2;
|
||||
}
|
||||
if (extensionMetadata.color3) {
|
||||
classRegistry.extensionInfo.color3 = extensionMetadata.color3;
|
||||
}
|
||||
if (extensionMetadata.tbShow) {
|
||||
classRegistry.extensionInfo.tbShow = extensionMetadata.tbShow;
|
||||
}
|
||||
}
|
||||
|
||||
return [].concat(headerCode, classRegistry.top, [], classRegistry.bottom, code, footerCode).join('\n');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,35 +12,17 @@
|
|||
import OpenButton from "$lib/ControlBar/OpenButton.svelte";
|
||||
import FullscreenButton from "$lib/ControlBar/FullscreenButton.svelte";
|
||||
import EaglerCraft from "$lib/EaglerCraft/EaglerCraft.svelte";
|
||||
import Documentation from "$lib/Documentation/Documentation.svelte";
|
||||
|
||||
// Modals
|
||||
import LoadExtensionModal from "$lib/MenuModals/LoadExtension.svelte";
|
||||
|
||||
// Extension Stuff
|
||||
import javascriptGenerator from '../resources/javascriptGenerator';
|
||||
import registerBlock from '../resources/register';
|
||||
|
||||
let EaglerBuilder = {
|
||||
extensions: {},
|
||||
BlockType: {
|
||||
"COMMAND": "command",
|
||||
"REPORTER": "reporter",
|
||||
"BOOLEAN": "boolean",
|
||||
"EVENT": "event",
|
||||
},
|
||||
ArgumentType: {
|
||||
"STRING": "string",
|
||||
"NUMBER": "number",
|
||||
"BOOLEAN": "boolean",
|
||||
"MENU": "menu",
|
||||
}
|
||||
};
|
||||
let Extensions = [];
|
||||
import ExtensionColorsModal from "$lib/MenuModals/ExtensionColors.svelte";
|
||||
import CreateBlockModal from "$lib/MenuModals/CreateBlock.svelte";
|
||||
|
||||
// Modal Scripts
|
||||
import CreateBlockModalScript from "$lib/MenuModals/createblock.js";
|
||||
|
||||
// Toolbox
|
||||
import Toolbox from "$lib/Toolbox/Toolbox.xml?raw";
|
||||
let EToolbox = Toolbox;
|
||||
|
||||
import JSZip from "jszip";
|
||||
import beautify from "js-beautify";
|
||||
|
|
@ -85,6 +67,7 @@
|
|||
import registerConversions from "../resources/blocks/conversions.js";
|
||||
import registerVariables from "../resources/blocks/variables.js";
|
||||
import registerJSON from "../resources/blocks/json.js";
|
||||
import registerBlocks from "../resources/blocks/blocks.js";
|
||||
import registerFunctions from "../resources/blocks/functions.js";
|
||||
import registerDebug from "../resources/blocks/debug.js";
|
||||
import registerPlayer from "../resources/blocks/player.js";
|
||||
|
|
@ -105,6 +88,7 @@
|
|||
registerConversions();
|
||||
registerVariables();
|
||||
registerJSON();
|
||||
registerBlocks();
|
||||
registerFunctions();
|
||||
registerDebug();
|
||||
registerPlayer();
|
||||
|
|
@ -147,6 +131,7 @@
|
|||
scaleSpeed: 1.1,
|
||||
},
|
||||
plugins: {
|
||||
toolbox: ContinuousToolboxPlugin.ContinuousToolbox,
|
||||
flyoutsVerticalToolbox: ContinuousToolboxPlugin.ContinuousFlyout,
|
||||
metricsManager: ContinuousToolboxPlugin.ContinuousMetrics,
|
||||
},
|
||||
|
|
@ -209,8 +194,7 @@
|
|||
lastGeneratedCode = code;
|
||||
}
|
||||
|
||||
|
||||
import * as pkg from '@blockly/workspace-minimap';
|
||||
import pkg from '@blockly/workspace-minimap';
|
||||
const { PositionedMinimap } = pkg;
|
||||
onMount(() => {
|
||||
console.log("ignore the warnings above we dont care about those");
|
||||
|
|
@ -227,186 +211,14 @@
|
|||
|
||||
const minimap = new PositionedMinimap(workspace);
|
||||
minimap.init();
|
||||
|
||||
let loadedExtensions = [];
|
||||
|
||||
EaglerBuilder.extensions.register = (extensionClass) => {
|
||||
let info = extensionClass.info();
|
||||
if (loadedExtensions.includes(info.id)) {
|
||||
alert("Extension has already been loaded.");
|
||||
return;
|
||||
} else {
|
||||
loadedExtensions.push(info.id);
|
||||
}
|
||||
|
||||
function FormatBlockText(text, args) {
|
||||
const regex = /\[([^\]]+)\]/g;
|
||||
|
||||
const blocklyText = text.replace(regex, (_, argid) => {
|
||||
const arg = argid.trim();
|
||||
if (args.hasOwnProperty(arg)) {
|
||||
return `%${Object.keys(args).indexOf(arg) + 1}`;
|
||||
}
|
||||
return `[${arg}]`;
|
||||
});
|
||||
|
||||
return blocklyText;
|
||||
}
|
||||
|
||||
function FormatMenu(menu) {
|
||||
let dropdownOptions = [];
|
||||
for (const item of menu) {
|
||||
if (typeof item === 'object' && !Array.isArray(item)) {
|
||||
dropdownOptions.push([item.text.toString(),item.value.toString()])
|
||||
} else if (typeof item === "string") {
|
||||
dropdownOptions.push([item,item])
|
||||
}
|
||||
}
|
||||
return dropdownOptions;
|
||||
}
|
||||
|
||||
function FormatArgument(id,arg) {
|
||||
switch (arg.type) {
|
||||
case EaglerBuilder.ArgumentType.STRING:
|
||||
return [{
|
||||
"type": "input_value",
|
||||
"name": id,
|
||||
"check": "String"
|
||||
}, `<value name="${id.replace(new RegExp("\"",'g'),"\\\"")}"><block type="literals_string"><field name="STRING">${(arg.default ? arg.default : "")}</field></block></value>`];
|
||||
case EaglerBuilder.ArgumentType.NUMBER:
|
||||
return [{
|
||||
"type": "input_value",
|
||||
"name": id,
|
||||
"check": "Number"
|
||||
}, `<value name="${id.replace(new RegExp("\"",'g'),"\\\"")}"><block type="literals_number"><field name="NUMBER">${(arg.default ? arg.default : 0)}</field></block></value>`];
|
||||
|
||||
case EaglerBuilder.ArgumentType.BOOLEAN:
|
||||
return [{
|
||||
"type": "input_value",
|
||||
"name": id,
|
||||
"check": "Boolean"
|
||||
}, ""];
|
||||
|
||||
case EaglerBuilder.ArgumentType.MENU:
|
||||
return [{
|
||||
"type": "field_dropdown",
|
||||
"name": id,
|
||||
"options": FormatMenu(info.menus[arg.menu])
|
||||
}, ""];
|
||||
|
||||
default:
|
||||
return [{
|
||||
"type": "input_dummy"
|
||||
}, ""];
|
||||
}
|
||||
}
|
||||
|
||||
function makeBlockJson(type,message0,args0) {
|
||||
switch (type) {
|
||||
case EaglerBuilder.BlockType.COMMAND:
|
||||
return {
|
||||
message0,
|
||||
args0,
|
||||
previousStatement: null,
|
||||
nextStatement: null,
|
||||
inputsInline: true,
|
||||
colour: info.color ? info.color : "#00ff55"
|
||||
};
|
||||
|
||||
case EaglerBuilder.BlockType.REPORTER:
|
||||
return {
|
||||
message0,
|
||||
args0,
|
||||
output: null,
|
||||
inputsInline: true,
|
||||
colour: info.color ? info.color : "#00ff55"
|
||||
};
|
||||
|
||||
case EaglerBuilder.BlockType.BOOLEAN:
|
||||
return {
|
||||
message0,
|
||||
args0,
|
||||
output: "Boolean",
|
||||
inputsInline: true,
|
||||
colour: info.color ? info.color : "#00ff55"
|
||||
};
|
||||
|
||||
case EaglerBuilder.BlockType.EVENT:
|
||||
if (args0.length == 0) {
|
||||
args0.push({
|
||||
"type": "input_dummy"
|
||||
})
|
||||
}
|
||||
args0.push({
|
||||
"type": "input_statement",
|
||||
"name": "EAGLERBUILDER_EVENT_INNERCODE",
|
||||
})
|
||||
message0 += ` ${args0.length - 1 == 1 ? `%${args0.length - 1}` : ""} %${args0.length}`
|
||||
return {
|
||||
message0,
|
||||
args0,
|
||||
inputsInline: true,
|
||||
colour: info.color ? info.color : "#00ff55"
|
||||
};
|
||||
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
let xmlblocks = "";
|
||||
|
||||
for (const block of info.blocks) {
|
||||
let xmlinputs = "";
|
||||
let message0 = FormatBlockText(block.text,block.arguments);
|
||||
let args0 = [];
|
||||
for (const argument in block.arguments) {
|
||||
let arg = FormatArgument(argument,block.arguments[argument],xmlinputs);
|
||||
args0.push(arg[0])
|
||||
xmlinputs += arg[1];
|
||||
}
|
||||
|
||||
let blockjson = makeBlockJson(block.type,message0,args0);
|
||||
|
||||
registerBlock(`${info.id}_${block.id}`,blockjson,(blocklyBlock) => {
|
||||
let args = {};
|
||||
for (const argument in block.arguments) {
|
||||
if (block.arguments[argument].type === EaglerBuilder.ArgumentType.MENU) {
|
||||
args[argument] = blocklyBlock.getFieldValue(argument);
|
||||
} else if (block.arguments[argument].type === EaglerBuilder.ArgumentType.NUMBER || block.arguments[argument].type === EaglerBuilder.ArgumentType.BOOLEAN || block.arguments[argument].type === EaglerBuilder.ArgumentType.STRING) {
|
||||
args[argument] = javascriptGenerator.valueToCode(blocklyBlock, argument, javascriptGenerator.ORDER_ATOMIC);
|
||||
}
|
||||
}
|
||||
let code = "";
|
||||
if (block.type == EaglerBuilder.BlockType.EVENT) {
|
||||
code = block.func(args,javascriptGenerator.statementToCode(blocklyBlock, 'EAGLERBUILDER_EVENT_INNERCODE'));
|
||||
} else {
|
||||
code = block.func(args);
|
||||
}
|
||||
console.log
|
||||
if (block.type == EaglerBuilder.BlockType.COMMAND || block.type == EaglerBuilder.BlockType.EVENT) {
|
||||
return `${code}\n`;
|
||||
} else if (block.type == EaglerBuilder.BlockType.REPORTER || block.type == EaglerBuilder.BlockType.BOOLEAN) {
|
||||
return [`(${code})`, javascriptGenerator.ORDER_ATOMIC];
|
||||
}
|
||||
})
|
||||
|
||||
xmlblocks += ` <block type="${info.id}_${block.id}">${xmlinputs}</block>\n`;
|
||||
}
|
||||
let extension = `<category name="${info.name ? info.name : info.id}" colour="${info.color ? info.color : "#00ff55"}">
|
||||
${xmlblocks}</category>`;
|
||||
EToolbox = EToolbox.replace('</xml>', extension + '</xml>');
|
||||
console.log(extension)
|
||||
workspace.updateToolbox(EToolbox);
|
||||
}
|
||||
});
|
||||
|
||||
function downloadProject() {
|
||||
// generate file name
|
||||
let filteredProjectName = (projectName || projectID).replace(/[^a-z0-9\-]+/gim, "_");
|
||||
let fileName = filteredProjectName + ".eb";
|
||||
let fileName = filteredProjectName + ".tb";
|
||||
if (!filteredProjectName) {
|
||||
fileName = "MyProject.eb";
|
||||
fileName = "MyProject.tb";
|
||||
}
|
||||
|
||||
// data
|
||||
|
|
@ -415,7 +227,8 @@ ${xmlblocks}</category>`;
|
|||
// modify data by me wow
|
||||
projectData = {
|
||||
blockly: projectData,
|
||||
extensions: Extensions
|
||||
metadata: extensionMetadata,
|
||||
images: extensionImageStates
|
||||
}
|
||||
|
||||
// zip
|
||||
|
|
@ -436,11 +249,11 @@ ${xmlblocks}</category>`;
|
|||
});
|
||||
}
|
||||
function loadProject() {
|
||||
fileDialog({ accept: ".eb" }).then((files) => {
|
||||
fileDialog({ accept: ".tb" }).then((files) => {
|
||||
if (!files) return;
|
||||
const file = files[0];
|
||||
|
||||
const projectNameIdx = file.name.lastIndexOf(".efb");
|
||||
const projectNameIdx = file.name.lastIndexOf(".tb");
|
||||
|
||||
JSZip.loadAsync(file.arrayBuffer()).then(async (zip) => {
|
||||
console.log("loaded zip file...");
|
||||
|
|
@ -452,9 +265,16 @@ ${xmlblocks}</category>`;
|
|||
.async("string");
|
||||
const projectJson = JSON.parse(projectJsonString);
|
||||
|
||||
// Load Extension stuff i guess
|
||||
for (const extension of projectJson.extensions) {
|
||||
eval(extension);
|
||||
// do your thing
|
||||
projectName = projectJson.metadata.name
|
||||
projectID = projectJson.metadata.id
|
||||
for (var i in projectJson.metadata) {
|
||||
var v = projectJson.metadata[i]
|
||||
extensionMetadata[i] = v
|
||||
}
|
||||
for (var i in projectJson.images) {
|
||||
var v = projectJson.images[i]
|
||||
extensionImageStates[i] = v
|
||||
}
|
||||
|
||||
// get project workspace xml stuffs
|
||||
|
|
@ -551,8 +371,7 @@ ${xmlblocks}</category>`;
|
|||
|
||||
// Modals
|
||||
const ModalState = {
|
||||
loadExtension: false,
|
||||
extensionGallery: false,
|
||||
extensionColors: false,
|
||||
};
|
||||
|
||||
function discordInvite() {
|
||||
|
|
@ -656,130 +475,66 @@ ${xmlblocks}</category>`;
|
|||
}
|
||||
</script>
|
||||
|
||||
{#if ModalState.loadExtension}
|
||||
<LoadExtensionModal
|
||||
on:completed={async (data) => {
|
||||
ModalState.loadExtension = false;
|
||||
if (data.detail.selected == "URL") {
|
||||
Extensions.push(await (await fetch(data.detail.URL)).text());
|
||||
eval(await (await fetch(data.detail.URL)).text());
|
||||
} else if (data.detail.selected == "Files") {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = () => {
|
||||
Extensions.push(fileReader.result);
|
||||
eval(fileReader.result);
|
||||
};
|
||||
fileReader.readAsText(data.detail.File);
|
||||
} else if (data.detail.selected == "Text") {
|
||||
Extensions.push(data.detail.Text);
|
||||
eval(data.detail.Text);
|
||||
}
|
||||
<CreateBlockModal
|
||||
color1={extensionMetadata.color1}
|
||||
color2={extensionMetadata.color2}
|
||||
color3={extensionMetadata.color3}
|
||||
/>
|
||||
{#if ModalState.extensionColors}
|
||||
<ExtensionColorsModal
|
||||
color1={extensionMetadata.color1}
|
||||
color2={extensionMetadata.color2}
|
||||
color3={extensionMetadata.color3}
|
||||
tbShow={extensionMetadata.tbShow}
|
||||
on:completed={(colors) => {
|
||||
ModalState.extensionColors = false;
|
||||
extensionMetadata.color1 = colors.detail.color1;
|
||||
extensionMetadata.color2 = colors.detail.color2;
|
||||
extensionMetadata.color3 = colors.detail.color3;
|
||||
extensionMetadata.tbShow = colors.detail.tbShow;
|
||||
updateGeneratedCode();
|
||||
}}
|
||||
on:cancel={() => {
|
||||
ModalState.loadExtension = false;
|
||||
ModalState.extensionColors = false;
|
||||
updateGeneratedCode();
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if ModalState.extensionGallery}
|
||||
<div class="full-modal">
|
||||
<div class="nav">
|
||||
<button class="back-button" on:click={() => {
|
||||
ModalState.extensionGallery = false;
|
||||
}}>
|
||||
<span class="back-span">
|
||||
<img
|
||||
class="arrow"
|
||||
draggable="false"
|
||||
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ4LjIgKDQ3MzI3KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5iYWNrLWljb248L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iYmFjay1pY29uIiBmaWxsPSIjRkZGRkZGIj4KICAgICAgICAgICAgPHBhdGggZD0iTTQuMTA4MDQ5MTIsOC41Nzc2NTA1NSBMOS4zMzIwMzYzOCwzLjM1MzY2MzI5IEM5LjYzODIwNDEzLDMuMDQ1NTgxOTkgMTAuMTE2NTkxMiwzLjA0NTU4MTk5IDEwLjQyMjc1OSwzLjM1MzY2MzI5IEwxNS42NDY3NDYyLDguNTc3NjUwNTUgQzE2LjE0NDI2ODgsOS4wNzUxNzMxNCAxNS43ODA2OTQ2LDkuODk2MDg1NDMgMTUuMDkxODE3Miw5Ljg5NjA4NTQzIEwxMi40ODkzOTEzLDkuODk2MDg1NDMgTDEwLjkzOTQxNzEsMTYuMDM4NTc1OSBDMTAuNzg2MzMzMiwxNi42MzM2ODk1IDEwLjE3Mzk5NzcsMTYuOTk1MzUwMiA5LjU4MDc5NzY4LDE2Ljg0MjI2NjMgQzkuMTU5ODE3MDIsMTYuNzQ4NTAyNCA4Ljg1MzY0OTI3LDE2LjQyMzE5OTIgOC43NTc5NzE4NCwxNi4wMzg1NzU5IEw3LjIwNzk5NzYsOS44OTYwODU0MyBMNC42NjI5NzgxNyw5Ljg5NjA4NTQzIEMzLjk3NDEwMDczLDkuODk2MDg1NDMgMy42MTA1MjY1Myw5LjA3NTE3MzE0IDQuMTA4MDQ5MTIsOC41Nzc2NTA1NSIgaWQ9IkZpbGwtMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS44NzczOTgsIDEwLjAwMDAwMCkgcm90YXRlKC05MC4wMDAwMDApIHRyYW5zbGF0ZSgtOS44NzczOTgsIC0xMC4wMDAwMDApICI+PC9wYXRoPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+"
|
||||
>
|
||||
Back
|
||||
</span>
|
||||
</button>
|
||||
<span class="full-modal-title">Choose an Extension</span>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="library">
|
||||
<div class="extension" on:click={() => {
|
||||
ModalState.extensionGallery = false;
|
||||
ModalState.loadExtension = true;
|
||||
}}>
|
||||
<img class="extension-img" draggable="false" src="/images/extensions/custom_extension.svg">
|
||||
<div class="extension-about">
|
||||
<span class="extension-title">
|
||||
Custom Extension
|
||||
</span>
|
||||
<br>
|
||||
<span class="extension-description">
|
||||
Load custom extensions from URLs, files, or JavaScript source code.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extension" on:click={async () => {
|
||||
Extensions.push(await (await fetch("/extensions/text-edit.js")).text());
|
||||
eval(await (await fetch("/extensions/text-edit.js")).text());
|
||||
ModalState.extensionGallery = false;
|
||||
}}>
|
||||
<img class="extension-img" draggable="false" src="/images/extensions/text_edit.png">
|
||||
<div class="extension-about">
|
||||
<span class="extension-title">
|
||||
Text Edit
|
||||
</span>
|
||||
<br>
|
||||
<span class="extension-description">
|
||||
Transform Text into other text.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extension" on:click={async () => {
|
||||
Extensions.push(await (await fetch("/extensions/operators-expansion.js")).text());
|
||||
eval(await (await fetch("/extensions/operators-expansion.js")).text());
|
||||
ModalState.extensionGallery = false;
|
||||
}}>
|
||||
<img class="extension-img" draggable="false" src="/images/extensions/operators_expansion.png">
|
||||
<div class="extension-about">
|
||||
<span class="extension-title">
|
||||
Operators Expansion
|
||||
</span>
|
||||
<br>
|
||||
<span class="extension-description">
|
||||
More operators like nand, xor, etc.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extension" on:click={async () => {
|
||||
Extensions.push(await (await fetch("/extensions/game-settings.js")).text());
|
||||
eval(await (await fetch("/extensions/game-settings.js")).text());
|
||||
ModalState.extensionGallery = false;
|
||||
}}>
|
||||
<img class="extension-img" draggable="false" src="/images/extensions/game_settings.svg">
|
||||
<div class="extension-about">
|
||||
<span class="extension-title">
|
||||
Game Settings
|
||||
</span>
|
||||
<br>
|
||||
<span class="extension-description">
|
||||
Manage in-game Settings.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<NavigationBar>
|
||||
<NavigationButton on:click={discordInvite}>Discord</NavigationButton>
|
||||
<NavigationButton on:click={github}>Github</NavigationButton>
|
||||
<NavigationDivider />
|
||||
<NavigationButton on:click={downloadProject}>Save</NavigationButton>
|
||||
<NavigationButton on:click={loadProject}>Load</NavigationButton>
|
||||
<NavigationButton on:click={loadProject}>Load</NavigationButton><!--
|
||||
<NavigationDivider />
|
||||
<input
|
||||
class="project-name"
|
||||
type="text"
|
||||
placeholder="Extension ID (ex: extensionID)"
|
||||
style="margin-left:4px;margin-right:4px"
|
||||
data-invalid={isExtensionIDInvalid(projectID)}
|
||||
bind:value={projectID}
|
||||
on:change={updateGeneratedCode}
|
||||
/>
|
||||
{#if isExtensionIDInvalid(projectID)}
|
||||
<p style="color:white;margin-left:4px">
|
||||
<b>Extension ID must be only letters and numbers.</b>
|
||||
</p>
|
||||
{/if}
|
||||
<NavigationDivider />
|
||||
<input
|
||||
class="project-name"
|
||||
type="text"
|
||||
placeholder="Extension Name (ex: Extension)"
|
||||
style="margin-left:4px;margin-right:4px"
|
||||
bind:value={projectName}
|
||||
on:change={updateGeneratedCode}
|
||||
/>-->
|
||||
</NavigationBar>
|
||||
<div class="main">
|
||||
<div class="row-menus">
|
||||
<div class="row-first-submenus">
|
||||
<div class="blockMenuButtons">
|
||||
<StyledButton on:click={() => {
|
||||
ModalState.extensionGallery = true;
|
||||
}}>Load Extension</StyledButton>
|
||||
</div>
|
||||
<div class="blocklyWrapper">
|
||||
<BlocklyComponent {config} locale={en} bind:workspace />
|
||||
|
|
@ -802,6 +557,7 @@ ${xmlblocks}</category>`;
|
|||
<EaglerCraft>
|
||||
</EaglerCraft>
|
||||
</div>
|
||||
<Documentation/>
|
||||
<div class="row-subsubmenus">
|
||||
<div class="codeActionsWrapper">
|
||||
<p style="margin-right: 12px"><b>Mod Code</b></p>
|
||||
|
|
@ -886,47 +642,6 @@ ${xmlblocks}</category>`;
|
|||
border: 1px solid dodgerblue;
|
||||
}
|
||||
|
||||
.full-modal {
|
||||
background: white;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
:global(body.dark) .full-modal {
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.full-modal-title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: white;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.back-span {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
|
|
@ -937,88 +652,6 @@ ${xmlblocks}</category>`;
|
|||
min-width: 870px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: var(--nav-height);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
background: rgb(86, 114, 205);
|
||||
}
|
||||
|
||||
:global(body.dark) .nav {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.library {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-grow: 1;
|
||||
flex-wrap: wrap;
|
||||
overflow-y: auto;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.extension {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 0.5rem;
|
||||
width: 300px;
|
||||
overflow: hidden;
|
||||
border: 1px #bbbbbb solid;
|
||||
cursor: pointer;
|
||||
margin: 0.5rem;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
align-self: stretch;
|
||||
flex-basis: 300px;
|
||||
}
|
||||
|
||||
:global(body.dark) .extension {
|
||||
border-color: #3b3b3b;
|
||||
}
|
||||
|
||||
.extension:hover, :global(body.dark) .extension:hover {
|
||||
border: 2px rgb(86, 114, 205) solid;
|
||||
}
|
||||
|
||||
.extension-img {
|
||||
width: 100%;
|
||||
height: 11.5rem;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.extension-about {
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
padding-left: 1.25rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.extension-title {
|
||||
margin: 0.25rem 0;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.extension-description {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
line-height: 1.375rem;
|
||||
padding-top: .3125rem;
|
||||
padding-bottom: .25rem;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
width: 236px;
|
||||
|
||||
|
|
@ -1225,4 +858,10 @@ ${xmlblocks}</category>`;
|
|||
:global(.blocklyScrollbarBackground:hover + .blocklyScrollbarHandle, .blocklyScrollbarHandle:hover) {
|
||||
fill: #575E75; /* fix strange scrollbar issue */
|
||||
}
|
||||
|
||||
:global(.blocklyToolboxDiv) {
|
||||
overflow-x: hidden;
|
||||
scrollbar-color: #797e8e80 transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,175 +0,0 @@
|
|||
<script>
|
||||
// Components
|
||||
import NavigationBar from "$lib/NavigationBar/NavigationBar.svelte";
|
||||
|
||||
// Variables
|
||||
let ceOpen = false;
|
||||
</script>
|
||||
|
||||
<NavigationBar>
|
||||
</NavigationBar>
|
||||
<div class="main">
|
||||
<div class="sidebar">
|
||||
<h3 class="title">EaglerBuilder Docs</h3>
|
||||
<a class="link" href="/docs/">Intro</a>
|
||||
<p class="link ce" style={ceOpen ? "--rot: 180deg" : "--rot: 90deg"} on:click={() => {ceOpen = !ceOpen}}>Custom Extensions</p>
|
||||
<div class="innerlinks" style={!ceOpen ? "height: 0px;" : "height: 100%;"}>
|
||||
<a class="link" href="/docs/extensions/">Overview</a>
|
||||
<a class="link" href="/docs/extensions/hello-world">Hello, world!</a>
|
||||
<a class="link" href="/docs/extensions/inputs">Dealing with inputs</a>
|
||||
<a class="link" href="/docs/extensions/events">Events</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--nav-height: 3rem;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: var(--nav-height);
|
||||
width: 100%;
|
||||
height: calc(100% - var(--nav-height));
|
||||
|
||||
min-width: 870px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: var(--nav-height);
|
||||
padding-top: 0px;
|
||||
padding-left: 10px;
|
||||
height: 100%;
|
||||
background-color: rgb(240, 240, 240);
|
||||
border-right: solid 4px rgb(220, 220, 220);
|
||||
}
|
||||
|
||||
:global(body.dark) .sidebar {
|
||||
background-color: rgb(30, 30, 30);
|
||||
border-right: solid 4px rgb(40, 40, 40);
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 240px;
|
||||
margin-right: 12px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: calc(100% + 0px);
|
||||
text-align: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: inherit;
|
||||
display: block;
|
||||
width: calc(100% - 20px);
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
background: rgba(0,0,0,.05);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
:global(body.dark) .link:hover {
|
||||
background: hsla(0,0%,100%,.05);
|
||||
}
|
||||
|
||||
.ce::after {
|
||||
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24"><path fill="rgba(0,0,0,0.5)" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></svg>') 50%/2rem 2rem;
|
||||
margin-left: 5px;
|
||||
min-width: 1.25rem;
|
||||
content: "";
|
||||
height: 1rem;
|
||||
transform: rotate(var(--rot));
|
||||
transition: transform 200ms linear;
|
||||
width: 1.25rem;
|
||||
filter: invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%);
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.innerlinks {
|
||||
position: relative;
|
||||
left: 10px;
|
||||
width: calc(100% - 10px);
|
||||
will-change: height;
|
||||
transition: height 326ms ease-in-out 0s;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:global(code) {
|
||||
background-color: hsla(0,0%,100%,.1);
|
||||
border: .1rem solid rgba(0,0,0,.1);
|
||||
border-radius: 0.4rem;
|
||||
font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
|
||||
font-size: 90%;
|
||||
padding: 0.1rem;
|
||||
}
|
||||
|
||||
/* Style the table */
|
||||
:global(table) {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Style table header */
|
||||
:global(th) {
|
||||
background-color: #f2f2f2;
|
||||
border: 1px solid #ddd;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
/* Style table cells */
|
||||
:global(td) {
|
||||
border: 1px solid #ddd;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
/* Style even rows */
|
||||
:global(tr:nth-child(even)) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
/* Style the table for dark mode */
|
||||
:global(body.dark) :global(table) {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Style table header for dark mode */
|
||||
:global(body.dark) :global(th) {
|
||||
background-color: #333; /* Dark background color */
|
||||
color: #fff; /* Light text color */
|
||||
border: 1px solid #555; /* Dark border color */
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
/* Style table cells for dark mode */
|
||||
:global(body.dark) :global(td) {
|
||||
border: 1px solid #555; /* Dark border color */
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
/* Style even rows for dark mode */
|
||||
:global(body.dark) :global(tr:nth-child(even)) {
|
||||
background-color: #444; /* Dark background color */
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<h1>EaglerBuilder Documentation</h1>
|
||||
<p><a href="/" target=_blank>EaglerBuilder</a> is a website made by <a href="https://discord.com/users/864214504941158441" target=_blank>@oeildelynx31</a> to create <a href="https://eaglerforge.github.io/" target=_blank>EaglerForge</a> Mods using Scratch-Like block coding. This is the place where its documentation is.</p>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<h1>Custom Extensions</h1>
|
||||
<p>Custom extensions are a way for you to add new blocks to EaglerBuilder using JavaScript.</p>
|
||||
<p>In this tutorial, we will describe how to build custom extensions. The pages can be navigated using the sidebar or links at the bottom of each page. We assume that you read each page in full and do the exercises listed (if any) before going to the next page.</p>
|
||||
<h1>Prerequisites</h1>
|
||||
<p>Custom extension development requires knowledge of writing JavaScript. If you aren't familiar with JavaScript, please learn it first. Your favorite search engine can help you find places to learn. If you don't know things like the difference between <code>"1"</code> and <code>1</code>, developing extensions will be very difficult. As volunteers, we don't have a lot of time to spend helping you learn JavaScript -- sorry.</p>
|
||||
<p>We assume that you have access to the developer tools built in to your browser or the desktop app. Typically this is accessible through right click > inspect element. In the desktop app, it can be shown with Ctrl+Shift+I (Option+Command+I on macOS). Writing JavaScript without access to the developer tools is extremely painful and not something we can provide help for.</p>
|
||||
<h1>Tutorial structure</h1>
|
||||
<p>This tutorial is follows a fundamentals-up approach. We're going to start with the most basic extensions imaginable that are effectively useless and gradually build up to things that are more useful.</p>
|
||||
<p>We know that some of you will be eager to start sharing your extensions around, but <strong>we ask that you read through this whole tutorial before publishing your extensions</strong> so that the extensions you share are actually useful.</p>
|
||||
<h1>Next steps</h1>
|
||||
<p>Next, let's <a href="/docs/extensions/hello-world">make your first extension</a>.</p>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<script>
|
||||
import CodeBlock from "$lib/DocumentationComponents/codeBlock.svelte";
|
||||
</script>
|
||||
|
||||
<h1>Events</h1>
|
||||
<p>Event blocks are for running scripts in response to something. An example of this is "when mod loaded do" - the event is when the mod loads. "every frame do" similarly starts in response to every frame. Event blocks can be used for anything that lets you run a callback or a piece of code (like if conditions).</p>
|
||||
<p>Event blocks are never actions they are conditions to callbacks. For example, consider this block you're familiar with:</p>
|
||||
<svg>
|
||||
<g transform="translate(-87.61963478915662, -294.04216867469876) scale(0.8012048192771084)">
|
||||
<g data-id="gLIO:p=UDJ2,h2Nf+})B" transform="translate(147, 387)">
|
||||
<path stroke="#bf8f00" fill="#ffbf00" d=" m 0,22 h 0 c 25,-22 71,-22 96,0 h 74.34375 a 4 4 0 0,1 4,4 v 26 V 30 V 62 V 66 a 4 4 0 0,1 -4,4 H 64 c -2,0 -3,1 -4,2 l -4,4 c -1,1 -2,2 -4,2 h -12 c -2,0 -3,-1 -4,-2 l -4,-4 c -1,-1 -2,-2 -4,-2 h -8 a 4 4 0 0,0 -4,4 v 16 a 4 4 0 0,0 4,4 h 8 c 2,0 3,1 4,2 l 4,4 c 1,1 2,2 4,2 h 12 c 2,0 3,-1 4,-2 l 4,-4 c 1,-1 2,-2 4,-2 H 170.34375 a 4 4 0 0,1 4,4 V 102 V 122 a 4 4 0 0,1 -4,4 h -166.34375 a 4 4 0 0,1 -4,-4 z"></path>
|
||||
<g transform="translate(8,36.5)">
|
||||
<text dominant-baseline="central" x="0" y="9.5" style="fill: white;font: 700 12pt "Source Code Pro", monospace;">when mod loaded do</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<p>When this block is compiled to code and ran it doesnt do anything on its own. We can create our own event block with similar functionality using <code>EaglerBuilder.BlockType.EVENT</code>:</p>
|
||||
<CodeBlock file="/extensions/when-mod-loaded-do.js" />
|
||||
<p>The block is defined similar to every other block. Note that it has a second argument in it's function which is the inner blocks compiled to code.</p>
|
||||
<h1>Excercises</h1>
|
||||
<p>1. Create an event-based block that runs once every second, another one every 5th second, and another every 10th second.</p>
|
||||
<p>2. Combine each of those event blocks into one block with a menu.</p>
|
||||
<p>3. Create a command block and event block and make them be like a message block.</p>
|
||||
<p>4. Combine each of those event blocks into one block with a menu.</p>
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
<script>
|
||||
import CodeBlock from "$lib/DocumentationComponents/codeBlock.svelte";
|
||||
</script>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
<p>Let's start by creating a very simple extension. This extension just adds a block that reports "Hello, world!":</p>
|
||||
<CodeBlock file="/extensions/hello-world.js" />
|
||||
<p>Save the code into a file called "hello-world.js".</p>
|
||||
<p>Now, go to the EaglerBuilder editor, click on the load extension button, and choose the "Custom Extension" option. Go to the File tab and click "Select File". Now find you file and select it. Then click load.</p>
|
||||
<p>After a second, an extension named "It works!" should appear in the sidebar. If it doesn't appear, open up your developer tools and look for any warnings in the console. Some of the most common errors are:</p>
|
||||
<ul>
|
||||
<li>Syntax error in the JavaScript. This should appear in your browser's developer tools.</li>
|
||||
<li>Runtime error in the JavaScript. This should appear in your browser's developer tools</li>
|
||||
</ul>
|
||||
<p>Now, we will dissect what is going on in this file in the order it runs.</p>
|
||||
<h1>Constructing and registering</h1>
|
||||
<CodeBlock code={"class MyExtension {"} />
|
||||
<p>This is a standard <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" target="_blank" rel="noopener noreferrer">JavaScript class</a>. It is conventional to define your extension in the form of a class. The name of the class doesn't matter, but we suggest making it somehow based on the extension's name. It doesn't have to be unique at this stage.</p>
|
||||
<CodeBlock code={"EaglerBuilder.extensions.register(new HelloWorld());"} />
|
||||
<p>This constructs your class into an object and introduces the special API that allows extensions to function: <code>EaglerBuilder</code>. There's not a lot on <code>EaglerBuilder</code>, but one of the most important functions is <code>EaglerBuilder.extensions.register</code>.</p>
|
||||
<p>Make sure to always call register() exactly once. If you don't call it, your extension will never get added. If you call it multiple times, an alert will pop up saying the extension has already been loaded.</p>
|
||||
<h1>info()</h1>
|
||||
<CodeBlock code={`info() {
|
||||
return {
|
||||
id: 'helloworld',
|
||||
name: 'It works!',
|
||||
blocks: [
|
||||
{
|
||||
id: 'hello',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'Hello!',
|
||||
func: () => {
|
||||
return '"World!"';
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}`} />
|
||||
<p>When you call register(), EaglerBuilder will then call the info() function on the provided object. This object must return an object with metadata about the extension. Some of the fields are <code>id</code>, <code>name</code>, and <code>blocks</code>. Here's a short summary of those:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Type</th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">id</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">A unique ID used only by this extension. Multiple extensions cannot share the same ID.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">name</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">The name of the extension that appears in the toolbox. If not provided, it will default to the extension id.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">blocks</td>
|
||||
<td style="text-align: center;">array</td>
|
||||
<td style="text-align: center;">A list of objects that describe the blocks in the project.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Here's a short summary of what each block should have:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Type</th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">id</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">A unique ID used only by this block. Multiple blocks cannot share the same ID.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">type</td>
|
||||
<td style="text-align: center;">EaglerBuilder.BlockType.*</td>
|
||||
<td style="text-align: center;">Determines the block's shape. Most commonly EaglerBuilder.BlockType.COMMAND, EaglerBuilder.BlockType.REPORTER, or EaglerBuilder.BlockType.BOOLEAN. See the table below for details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">text</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">The text that will appear in the editor for the block. There is a bit of special syntax here for dealing with arguments that will be discussed in the next segment.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">arguments</td>
|
||||
<td style="text-align: center;">object</td>
|
||||
<td style="text-align: center;">Optional. Discussed in the next section.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">func</td>
|
||||
<td style="text-align: center;">function</td>
|
||||
<td style="text-align: center;">The Function of the block which will return the corresponding code from the Block.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>These are the acceptable values for type:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
<th style="text-align: center;">Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.BlockType.COMMAND</td>
|
||||
<td style="text-align: center;">A block that doesn't report a value </td>
|
||||
<td style="text-align: center;">wait 1000 (ms)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.BlockType.REPORTER</td>
|
||||
<td style="text-align: center;">A round block that usually reports a string or number</td>
|
||||
<td style="text-align: center;">current FPS, 'string'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.BlockType.BOOLEAN</td>
|
||||
<td style="text-align: center;">A block with pointy edges that reports a boolean (true or false)</td>
|
||||
<td style="text-align: center;">is key SPACE pressed?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.BlockType.EVENT</td>
|
||||
<td style="text-align: center;">A block which has Inner Blocks. Discussed later.</td>
|
||||
<td style="text-align: center;">when mod loaded do</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h1>The blocks</h1>
|
||||
<CodeBlock code={`(args) => {
|
||||
return '"Whatever, ' + args.name + '"';
|
||||
}`} />
|
||||
<p>This is a function that will return the code from a block. In this case, our function is very simple and just returns a "Whatever, " following the argument name from the block. Blocks are expected to return a string.</p>
|
||||
<h1>Excercises</h1>
|
||||
<p>1. Change the "Whatever," block to return your favorite number instead. Remember to rename the block accordingly.</p>
|
||||
<p>2. Change the block's id.</p>
|
||||
<p>3. Add another block. Make this block use a <code>type</code> of <code>EaglerBuilder.BlockType.BOOLEAN</code> and return code which when ran returns a boolean (true or false) at random.</p>
|
||||
<h1>Next steps</h1>
|
||||
<p>Next, let's <a href="/docs/extensions/inputs">allow our blocks to take in arguments</a>.</p>
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
<script>
|
||||
import CodeBlock from "$lib/DocumentationComponents/codeBlock.svelte";
|
||||
</script>
|
||||
|
||||
<h1>Dealing with inputs</h1>
|
||||
<p>Often you will want your blocks to take something in as an "input", "argument", or "parameter". Let's learn how to do that with a new example:</p>
|
||||
<CodeBlock file="/extensions/nor.js"/>
|
||||
<p>Save this code to a file called "nor.js" beside "hello-world.js", and load it the same way you loaded the hello world extension. Most of the code is very similar to the hello world extension. Notice that the nor block in this extension will be false if any of the inputs are true but be true when none are true.</p>
|
||||
<p>Now let's talk about the arguments.</p>
|
||||
<p>To add arguments to a block, you give it an <code>arguments</code> property. It should be set to an object that contains other objects. Each property you put in <code>arguments</code> corresponds to a single argument. Each one has a name. The names can be all capitals or any format you desire.</p>
|
||||
<p>Here's a summary of the most common properties to set for an argument:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Type</th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">type</td>
|
||||
<td style="text-align: center;">EaglerBuilder.ArgumentType.*</td>
|
||||
<td style="text-align: center;">Determines the shape of the input and what it accepts. See the table below for acceptable values.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">default</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">Optional. The default value in the toolbox. Unique to inputs with type EaglerBuilder.ArgumentType.STRING and EaglerBuilder.ArgumentType.NUMBER.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">menu</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">Unique to inputs with type EaglerBuilder.ArgumentType.MENU. Discussed later.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>These are the acceptable values for type:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
<th style="text-align: center;">Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.ArgumentType.STRING</td>
|
||||
<td style="text-align: center;">Any text</td>
|
||||
<td style="text-align: center;">apple, 123, true</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.ArgumentType.NUMBER</td>
|
||||
<td style="text-align: center;">Any number</td>
|
||||
<td style="text-align: center;">123</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.ArgumentType.BOOLEAN</td>
|
||||
<td style="text-align: center;">True or false</td>
|
||||
<td style="text-align: center;">true</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">EaglerBuilder.ArgumentType.MENU</td>
|
||||
<td style="text-align: center;">An input with a menu (dropdown)</td>
|
||||
<td style="text-align: center;">ANY</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Next, EaglerBuilder needs to know where to put each of the arguments in the block. Are they at the start, end, or somewhere in the middle? It can't guess, so you have to tell it. To do this, you use the <code>text</code> property on the block by using <code>[ARGUMENT_NAME]</code> syntax to denote where each input goes. Each argument in the <code>arguments</code> object should appear in <code>text</code> exactly once. Arguments can be in any order, it doesn't matter.</p>
|
||||
<p>When EaglerBuilder runs your block functions and compiles your blocks, it will pass in an object for the first value. This object will contain a value for each argument name that the block has. Conventionally we call this <code>args</code> or use destructuring syntax. As an example, if the block has an argument named <code>X</code> and <code>Y</code>, these could be accessed in any of these ways:</p>
|
||||
<CodeBlock code={`// Using args.XYZ format...
|
||||
function(args) {
|
||||
console.log(args.X, args.Y);
|
||||
}
|
||||
|
||||
// Or using destructuring...
|
||||
function({X, Y}) {
|
||||
console.log(X, Y);
|
||||
}`} />
|
||||
<p>Arguments are always provided as a string because they are another snippet of code.</p>
|
||||
<h1>Menus</h1>
|
||||
<p>Sometimes you might prefer your blocks to have a dropdown. These are called menus.</p>
|
||||
<CodeBlock file="/extensions/strings-1.js"/>
|
||||
<p>To make an argument into a menu, set its <code>type</code> to <code>EaglerBuilder.ArgumentType.MENU</code> and set its <code>menu</code> property to the name of the menu. This corresponds to a new property in the object returned by info(): <code>menus</code>.</p>
|
||||
<p><code>menus</code> is an array of strings / objects. Each item in <code>menus</code> is typically a string or object with these properties:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;"></th>
|
||||
<th style="text-align: center;">Type</th>
|
||||
<th style="text-align: center;">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">text</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">The Text shown in the dropdown.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">value</td>
|
||||
<td style="text-align: center;">string</td>
|
||||
<td style="text-align: center;">The Text returned from the argument.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<CodeBlock file="/extensions/strings-2.js"/>
|
||||
<p>Notice that, although the dropdown displays UPPERCASE in the editor, the block actually receives "up".</p>
|
||||
<h1>Excercises</h1>
|
||||
<p>1. Add a block that does the same thing as the built-in "join" block. It should take two arguments and produce a new string joining them together. Make sure your block casts the arguments to strings so when someone runs "join ((1 + 2)) ((3 + 4))" they get "(1 + 2)(3 + 4)" not 10.</p>
|
||||
<p>2. Create a boolean block that takes a number argument and a menu argument with the options "odd" and "even". The block should return whether the given number is either odd or even, as the menu says.</p>
|
||||
<h1>Next steps</h1>
|
||||
<p>Next, let's see <a href="/docs/extensions/events">how to make blocks like "every frame do" or "when mod loaded do"</a>.</p>
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
class GameSettings {
|
||||
info() {
|
||||
return {
|
||||
id: 'gamesettings',
|
||||
name: 'Game Settings',
|
||||
color: '#999999',
|
||||
blocks: [
|
||||
{
|
||||
id: 'setnumsetting',
|
||||
type: EaglerBuilder.BlockType.COMMAND,
|
||||
text: 'set [setting] (number) to [value]',
|
||||
arguments: {
|
||||
setting: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: "ALL_NUMBER_GAME_SETTINGS"
|
||||
},
|
||||
value: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 10
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `ModAPI.settings.${args.setting} = ${args.value}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'setboolsetting',
|
||||
type: EaglerBuilder.BlockType.COMMAND,
|
||||
text: 'set [setting] (boolean) to [value]',
|
||||
arguments: {
|
||||
setting: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: "ALL_BOOLEAN_GAME_SETTINGS"
|
||||
},
|
||||
value: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `ModAPI.settings.${args.setting} = ${args.value}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'getsetting',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'get [setting]',
|
||||
arguments: {
|
||||
setting: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: "ALL_TEXTUAL_GAME_SETTINGS"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `ModAPI.settings.${args.setting}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'settingisenabled',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[setting] is enabled?',
|
||||
arguments: {
|
||||
setting: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: "ALL_BOOLEAN_GAME_SETTINGS"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `ModAPI.settings.${args.setting}`;
|
||||
}
|
||||
},
|
||||
],
|
||||
menus: {
|
||||
ALL_NUMBER_GAME_SETTINGS: [
|
||||
{
|
||||
text: "Render Distance",
|
||||
value: "renderDistanceChunks"
|
||||
},
|
||||
{
|
||||
text: "Mouse Sensitivity",
|
||||
value: "mouseSensitivity"
|
||||
},
|
||||
{
|
||||
text: "FOV",
|
||||
value: "fovSetting"
|
||||
},
|
||||
],
|
||||
ALL_BOOLEAN_GAME_SETTINGS: [
|
||||
{
|
||||
text: "Inverted Mouse",
|
||||
value: "invertMouse"
|
||||
},
|
||||
{
|
||||
text: "Hidden Gui",
|
||||
value: "hideGUI"
|
||||
}
|
||||
],
|
||||
ALL_TEXTUAL_GAME_SETTINGS: [
|
||||
{
|
||||
text: "Render Distance",
|
||||
value: "renderDistanceChunks"
|
||||
},
|
||||
{
|
||||
text: "Mouse Sensitivity",
|
||||
value: "mouseSensitivity"
|
||||
},
|
||||
{
|
||||
text: "FOV",
|
||||
value: "fovSetting"
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new GameSettings());
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
class HelloWorld {
|
||||
info() {
|
||||
return {
|
||||
id: 'helloworld',
|
||||
name: 'It works!',
|
||||
blocks: [
|
||||
{
|
||||
id: 'hello',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'Hello!',
|
||||
func: () => {
|
||||
return '"World!"';
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new HelloWorld());
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
class NorExample {
|
||||
info() {
|
||||
return {
|
||||
id: 'norexample',
|
||||
name: 'Nor',
|
||||
blocks: [
|
||||
{
|
||||
id: 'nor',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] nor [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `!(${args.A} || ${args.B})`;
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new NorExample());
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
class OperatorsExpansion {
|
||||
info() {
|
||||
return {
|
||||
id: 'operatorsexpansion',
|
||||
name: 'Operators Expansion',
|
||||
color: "#59C059",
|
||||
blocks: [
|
||||
{
|
||||
id: 'nand',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] nand [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `!(${args.A} && ${args.B})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'nor',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] nor [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `!(${args.A} || ${args.B})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'xor',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] xor [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `(${args.A} || ${args.B}) && !(${args.A} && ${args.B})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'lessthanorequalto',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] <= [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.A} <= ${args.B}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'greaterthanorequalto',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] >= [B]',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.BOOLEAN,
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.A} >= ${args.B}`;
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
id: 'contains',
|
||||
type: EaglerBuilder.BlockType.BOOLEAN,
|
||||
text: '[A] contains [B]?',
|
||||
arguments: {
|
||||
A: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Apple"
|
||||
},
|
||||
B: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Banana"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.A}.includes(${args.B})`;
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new OperatorsExpansion());
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
class SampleExtension {
|
||||
info() {
|
||||
return {
|
||||
"name": "Sample Extension",
|
||||
"id": "sample",
|
||||
"blocks": [{
|
||||
"type": EaglerBuilder.BlockType.COMMAND,
|
||||
"id": "cool",
|
||||
"text": "My Cool Block [cooly]",
|
||||
"arguments": {
|
||||
cooly: {
|
||||
"type": EaglerBuilder.ArgumentType.STRING,
|
||||
"default": "hi"
|
||||
}
|
||||
},
|
||||
"func": (args) => {
|
||||
return `console.log(${args.cooly})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": EaglerBuilder.BlockType.COMMAND,
|
||||
"id": "waitif",
|
||||
"text": "wait [time] seconds if [condition]",
|
||||
"arguments": {
|
||||
time: {
|
||||
"type": EaglerBuilder.ArgumentType.NUMBER
|
||||
},
|
||||
condition: {
|
||||
"type": EaglerBuilder.ArgumentType.BOOLEAN
|
||||
}
|
||||
},
|
||||
"func": (args) => {
|
||||
return `if (${args.condition}) {await new Promise(resolve => setTimeout(resolve, ${args.time * 1000}))}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": EaglerBuilder.BlockType.COMMAND,
|
||||
"id": "test",
|
||||
"text": "test menu [menu]",
|
||||
"arguments": {
|
||||
menu: {
|
||||
"type": EaglerBuilder.ArgumentType.MENU,
|
||||
"menu": "test",
|
||||
}
|
||||
},
|
||||
"func": (args) => {
|
||||
return `console.log("${args.menu}")`;
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": EaglerBuilder.BlockType.BOOLEAN,
|
||||
"id": "getpropertyboolean",
|
||||
"text": "get player property [PROPERTIES]",
|
||||
"arguments": {
|
||||
PROPERTIES: {
|
||||
"type": EaglerBuilder.ArgumentType.MENU,
|
||||
"menu": "is",
|
||||
}
|
||||
},
|
||||
"func": (args) => {
|
||||
const PROPERTY = args.PROPERTIES;
|
||||
let code;
|
||||
if (PROPERTY === "isdead") {
|
||||
code = 'ModAPI.player.isDead';
|
||||
} else if (PROPERTY === "isinvisible") {
|
||||
code = `ModAPI.player.isInvisible()`
|
||||
} else if (PROPERTY === "isinweb") {
|
||||
code = `ModAPI.player.isInWeb`
|
||||
} else if (PROPERTY === "issprinting") {
|
||||
code = `ModAPI.player.isSprinting()`
|
||||
} else if (PROPERTY === "issneaking") {
|
||||
code = `ModAPI.player.isSneaking()`
|
||||
} else if (PROPERTY === "issilent") {
|
||||
code = `ModAPI.player.isSilent()`
|
||||
} else if (PROPERTY === "canedit") {
|
||||
code = `ModAPI.player.isAllowEdit()`
|
||||
} else if (PROPERTY === "onground") {
|
||||
code = `ModAPI.player.onGround`
|
||||
} else if (PROPERTY === "isdead") {
|
||||
code = `ModAPI.player.isDead`
|
||||
} else if (PROPERTY === "ismoving") {
|
||||
code = `ModAPI.player.isMoving()`
|
||||
}
|
||||
return code;
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": EaglerBuilder.BlockType.EVENT,
|
||||
"id": "delayif",
|
||||
"text": "delay [time] seconds if [condition]",
|
||||
"arguments": {
|
||||
time: {
|
||||
"type": EaglerBuilder.ArgumentType.NUMBER
|
||||
},
|
||||
condition: {
|
||||
"type": EaglerBuilder.ArgumentType.BOOLEAN
|
||||
}
|
||||
},
|
||||
"func": (args,innercode) => {
|
||||
return `if (${args.condition}) {
|
||||
setTimeout(() => {${innercode}}, ${args.time * 1000})
|
||||
}`;
|
||||
}
|
||||
}],
|
||||
"menus": {
|
||||
"test": [
|
||||
"test",
|
||||
{
|
||||
"text": "different",
|
||||
"value": "menu"
|
||||
}
|
||||
],
|
||||
"is": [
|
||||
{
|
||||
"text": "is dead",
|
||||
"value": "isdead"
|
||||
},
|
||||
{
|
||||
"text": "is invisible",
|
||||
"value": "isinvisible"
|
||||
},
|
||||
{
|
||||
"text": "is in web",
|
||||
"value": "isinweb"
|
||||
},
|
||||
{
|
||||
"text": "is sprinting",
|
||||
"value": "issprinting"
|
||||
},
|
||||
{
|
||||
"text": "is sneaking",
|
||||
"value": "issneaking"
|
||||
},
|
||||
{
|
||||
"text": "is silent",
|
||||
"value": "issilent"
|
||||
},
|
||||
{
|
||||
"text": "can edit",
|
||||
"value": "canedit"
|
||||
},
|
||||
{
|
||||
"text": "on ground",
|
||||
"value": "onground"
|
||||
},
|
||||
{
|
||||
"text": "is moving",
|
||||
"value": "ismoving"
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new SampleExtension());
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
class Strings1 {
|
||||
info() {
|
||||
return {
|
||||
id: 'strings1example',
|
||||
name: 'Encoding',
|
||||
blocks: [
|
||||
{
|
||||
id: 'convert',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'convert [TEXT] to [FORMAT]',
|
||||
arguments: {
|
||||
TEXT: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: 'Apple'
|
||||
},
|
||||
FORMAT: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: 'FORMAT_MENU'
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
if (args.FORMAT === 'uppercase') {
|
||||
return `${args.TEXT}.toUpperCase()`;
|
||||
} else {
|
||||
return `${args.TEXT}.toLowerCase()`;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
menus: {
|
||||
FORMAT_MENU: ['uppercase', 'lowercase']
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new Strings1());
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
class Strings2 {
|
||||
info() {
|
||||
return {
|
||||
id: 'strings2example',
|
||||
name: 'Encoding',
|
||||
blocks: [
|
||||
{
|
||||
id: 'convert',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'convert [TEXT] to [FORMAT]',
|
||||
arguments: {
|
||||
TEXT: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: 'Apple'
|
||||
},
|
||||
FORMAT: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: 'FORMAT_MENU'
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
if (args.FORMAT === 'up') {
|
||||
return `${args.TEXT}.toUpperCase()`;
|
||||
} else {
|
||||
return `${args.TEXT}.toLowerCase()`;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
menus: {
|
||||
FORMAT_MENU: [
|
||||
{
|
||||
text: 'uppercase',
|
||||
value: 'up'
|
||||
},
|
||||
{
|
||||
text: 'lowercase',
|
||||
value: 'low'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new Strings2());
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
class TextEdit {
|
||||
info() {
|
||||
return {
|
||||
id: 'textedit',
|
||||
name: 'Text Edit',
|
||||
color: "#00ff00",
|
||||
blocks: [
|
||||
{
|
||||
id: 'replaceinwith',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'replace [string] in [text] with [replace]',
|
||||
arguments: {
|
||||
string: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Hello"
|
||||
},
|
||||
text: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Hello, world!"
|
||||
},
|
||||
replace: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Goodbye"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.text}.replace(new RegExp(${args.string},'g'),${args.replace})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'lettersfromtoof',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'letters from [start] to [end] of [text]',
|
||||
arguments: {
|
||||
start: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 1
|
||||
},
|
||||
end: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 3
|
||||
},
|
||||
text: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Banana"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.text}.substring(${args.start}-1,${args.end})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'removeletterof',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'remove letter [index] of [text]',
|
||||
arguments: {
|
||||
index: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 3
|
||||
},
|
||||
text: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Pineapple"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.text}.slice(0, ${args.index} - 1) + ${args.text}.slice(${args.index})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'removelettersfromtoof',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'remove letters from [start] to [end] of [text]',
|
||||
arguments: {
|
||||
start: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 1
|
||||
},
|
||||
end: {
|
||||
type: EaglerBuilder.ArgumentType.NUMBER,
|
||||
default: 3
|
||||
},
|
||||
text: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Grape"
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.text}.slice(0, ${args.start} - 1) + ${args.text}.slice(${args.end})`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'convert',
|
||||
type: EaglerBuilder.BlockType.REPORTER,
|
||||
text: 'convert [text] to [format]',
|
||||
arguments: {
|
||||
text: {
|
||||
type: EaglerBuilder.ArgumentType.STRING,
|
||||
default: "Apple"
|
||||
},
|
||||
format: {
|
||||
type: EaglerBuilder.ArgumentType.MENU,
|
||||
menu: 'FORMAT_MENU'
|
||||
}
|
||||
},
|
||||
func: (args) => {
|
||||
return `${args.text}.${args.format}()`;
|
||||
}
|
||||
}
|
||||
],
|
||||
menus: {
|
||||
FORMAT_MENU: [
|
||||
{
|
||||
text: "uppercase",
|
||||
value: "toUpperCase"
|
||||
},
|
||||
{
|
||||
text: "lowercase",
|
||||
value: "toLowerCase"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new TextEdit());
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
class WhenModLoadedDo {
|
||||
info() {
|
||||
return {
|
||||
id: 'eventexample',
|
||||
name: 'Event Block Example',
|
||||
blocks: [
|
||||
{
|
||||
id: 'modload',
|
||||
type: EaglerBuilder.BlockType.EVENT,
|
||||
text: 'when mod loaded do',
|
||||
func: (args, innercode) => {
|
||||
return `${innercode.indexOf('await') > -1 ? 'async' : ''} function onload() {\n${innercode}}`;
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
EaglerBuilder.extensions.register(new WhenModLoadedDo());
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 758 KiB |
BIN
static/favicon_dark.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
|
@ -1,90 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="600"
|
||||
height="300"
|
||||
version="1.1"
|
||||
id="svg10"
|
||||
sodipodi:docname="cf07199bb768b01e6ac2a5c68fd8c3bb.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="2.2733333"
|
||||
inkscape:cx="300"
|
||||
inkscape:cy="149.78006"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1013"
|
||||
inkscape:window-x="1366"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10" />
|
||||
<path
|
||||
fill="#0fbd8c"
|
||||
d="M0 0h600v300H0Z"
|
||||
style="stroke-width:0.898027;fill:#6d85d1;fill-opacity:1"
|
||||
id="path1" />
|
||||
<path
|
||||
fill="#ffd641"
|
||||
d="M-19.344061 186C-19.344061 9.631143 123.63114-133.34406 300-133.34406c176.36885 0 319.34406 142.975203 319.34406 319.34406 0 176.36885-142.97521 319.34406-319.34406 319.34406-176.36886 0-319.344061-142.97521-319.344061-319.34406Z"
|
||||
style="fill:#3b57b5;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path2" />
|
||||
<path
|
||||
fill="#ffc800"
|
||||
d="M20.155927 186C20.155927 31.446397 145.44638-93.844074 300-93.844074c154.5536 0 279.84407 125.29046 279.84407 279.844074 0 154.5536-125.29046 279.84407-279.84407 279.84407S20.155937 340.55361 20.155937 186Z"
|
||||
style="fill:#6d85d1;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path3" />
|
||||
<path
|
||||
fill="#ffd641"
|
||||
d="M60.155932 186c0-132.462224 107.381848-239.844074 239.844078-239.844074 132.46222 0 239.84406 107.38185 239.84406 239.844074 0 132.46222-107.38185 239.84407-239.84406 239.84407-132.46223 0-239.844078-107.38185-239.844078-239.84407Z"
|
||||
style="fill:#3b57b5;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path4" />
|
||||
<path
|
||||
fill="#ffc800"
|
||||
d="M100.65593 185.99999C100.65593 75.905307 189.9053-13.344074 300-13.344074c110.09469 0 199.34407 89.249381 199.34407 199.344074 0 110.09469-89.24938 199.34407-199.34406 199.34407-110.09469 0-199.34406-89.24938-199.34406-199.34406z"
|
||||
style="fill:#6d85d1;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path5" />
|
||||
<path
|
||||
fill="#ffd641"
|
||||
d="M139.90593 185.99999c0-88.417506 71.67656-160.094063 160.09407-160.094063S460.09407 97.582494 460.09407 186c0 88.41751-71.67656 160.09407-160.09406 160.09407-88.41752 0-160.09407-71.67656-160.09407-160.09406z"
|
||||
style="fill:#3b57b5;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path6" />
|
||||
<path
|
||||
fill="#ffc800"
|
||||
d="M180.65593 185.99999c0-65.9119 53.43216-119.344064 119.34408-119.344064 65.9119 0 119.34407 53.432164 119.34407 119.344074 0 65.9119-53.43216 119.34407-119.34406 119.34407s-119.34407-53.43216-119.34407-119.34406z"
|
||||
style="fill:#6d85d1;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path7" />
|
||||
<path
|
||||
fill="#ffd641"
|
||||
d="M219.90593 185.99999c0-44.23473 35.85933-80.09406 80.09407-80.09406 44.23473 0 80.09407 35.85933 80.09407 80.09407 0 44.23473-35.85933 80.09407-80.09406 80.09407s-80.09406-35.85933-80.09406-80.09406z"
|
||||
style="fill:#3b57b5;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path8" />
|
||||
<path
|
||||
fill="#ffc800"
|
||||
d="M260.0726 186c0-22.05129 17.87611-39.9274 39.9274-39.9274 22.05129 0 39.9274 17.87611 39.9274 39.9274 0 22.05129-17.87611 39.9274-39.9274 39.9274-22.05129 0-39.9274-17.87611-39.9274-39.9274z"
|
||||
style="fill:#6d85d1;fill-opacity:1;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
transform="matrix(.93943 0 0 .93943 18.172307 -24.73317)"
|
||||
id="path9" />
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M169.4570363 135.41041823c23.03677403 0 26.10859254-12.286654 26.10859254-23.03801407 0-9.21495762-1.53578243-16.89437707-1.53578243-26.10859254 0-9.21421548-1.53578243-18.42967006-1.53578243-26.1085916 0-32.25222486 19.96619557-46.07478812 52.21841572-46.07478812h12.28664461v29.18042138h-6.14324245c-15.35787128 0-19.96620496 9.2149473-19.96620496 24.57328828 0 6.1432697 1.53579182 12.28664367 1.53579182 19.96618524 0 6.14327064 1.53578243 13.82256795 1.53578243 23.03801408 0 26.10859254-10.75074005 35.32404806-29.18042044 39.93116049 18.42968039 4.60746942 29.18042044 13.82254916 29.18042044 39.9311417 0 9.21496702-1.53578243 16.89439586-1.53578243 23.03678343 0 6.14327064-1.53579182 13.82255856-1.53579182 18.429671 0 15.35785249 4.6074788 24.57328922 19.96620496 24.57328922h6.14324245v29.18041104h-12.2866446c-30.71693563 0-50.68189116-12.2866446-50.68189116-46.07477871 0-9.21495763 0-16.89438646 1.53578243-26.10860194 1.53579183-9.21420608 1.53579183-18.4296616 1.53579183-26.10859254 0-9.21495762-3.07169638-23.03800468-26.10860194-23.03800468zm261.0859254 26.10859255c-23.03677403 0-26.10859254 13.82254916-26.10859254 23.03676464 0 9.21495762 1.53578243 16.89437706 1.53578243 26.10859254 1.53579183 9.21495762 1.53579183 18.429671 1.53579183 26.10859254 0 33.78875413-21.5014801 46.07478811-52.21842512 46.07478811h-12.28664461v-26.10859254h6.14326124c15.35785249 0 19.96619557-9.21495762 19.96619557-24.57329861 0-6.14326124 0-12.28664461-1.53579183-18.429671 0-7.6791658-1.53578243-15.35785248-1.53578243-23.03677403 0-26.10859254 10.75074006-35.32403867 29.18041105-39.9311511-18.429671-4.60747881-29.18041105-13.82255856-29.18041105-39.9311511 0-9.21495762 1.53578243-16.89437707 1.53578243-23.03801408 1.53579183-7.6791658 1.53579183-13.82254916 1.53579183-19.96618524 0-15.35785248-6.14327064-23.03800186-19.96619557-24.57329015h-6.14326124V14.07919938h12.2866446c32.25222016 0 52.21842513 13.82256325 52.21842513 46.0747806 0 9.21495668-1.53579183 16.89438551-1.53579183 26.10860099-1.53578243 9.21495762-1.53578243 18.429671-1.53578243 26.10859254 0 10.75073066 3.07168699 23.03800468 26.10859254 23.03800468z"
|
||||
id="path10" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB |