5 Commits

Author SHA1 Message Date
2eef1b5c4e Update translations for skin editor. 2023-03-14 17:27:05 +08:00
c18ceb50d4 Update skin structure in editor. 2023-03-14 17:24:32 +08:00
27ca1a7292 Implement expression in skin editor. 2023-03-14 17:22:48 +08:00
dc59176eac Fix encoding for skin editor. 2023-03-14 16:59:37 +08:00
aec7470ff8 Optimize css for skin editor. 2023-03-14 16:58:03 +08:00
5 changed files with 162 additions and 122 deletions

View File

@@ -22,14 +22,14 @@ body {
cursor: pointer;
}
.tgbtn-active {
background-color: lightblue;
}
.tgbtn:hover {
background-color: lightgray;
}
.tgbtn-active, .tgbtn-active:hover {
background-color: lightblue;
}
#toolbar .tgbtn {
min-width: 64px;
height: 100%;
@@ -124,9 +124,6 @@ input {
width: 16px;
}
.t-statement > .btn {
}
.t-node:hover > .btn {
transition: 0.25s;
height: 16px;
@@ -158,15 +155,32 @@ input {
.t-exp {
border-top: solid 1px gray;
vertical-align: top;
}
.t-exp.t-inline {
padding: 2px 4px;
margin: 0 2px;
padding: 2px;
}
.t-exp .t-inline {
margin: 0 2px 2px 2px;
}
.t-exp .t-statement {
margin: 0;
border: 0;
border-left: solid 1px red;
padding: 0;
}
.t-exp:hover {
border-top: solid 3px gray;
}
.t-exp .btn-add:not(:only-child) {
display: none;
}
.t-input {
display: inline-block;
@@ -267,12 +281,12 @@ input {
background-color: black;
color: white;
}
.tgbtn-active {
background-color: darkslateblue;
}
.tgbtn:hover {
background-color: gray;
}
.tgbtn-active, .tgbtn-active:hover {
background-color: darkslateblue;
}
.t-internal {
background-color: dimgray;
}

View File

@@ -11,11 +11,9 @@ var cel;
var clist;
var blocklists = {
"block.element": ["statement.obj", "statement.select"],
"block.filter": ["statement.filter.type", "statement.filter.exp"],
"block.object": ["statement.comp", "statement.prop", "statement.filter"],
"block.element": ["statement.select", "statement.obj", "statement.comp", "statement.prop"],
"block.root": ["statement.select", "statement.define"],
"block.select": ["statement.select.type", "statement.select.exp"],
"block.select": ["statement.select.type", "statement.select.exp", "statement.select.anchor", "statement.select.atanchor"],
};
var ilid = 0;
@@ -36,15 +34,25 @@ var inputlists = {
var statementlists = {
"statement.comp": ["input.comp"],
"statement.define": ["input.ident", "exp"],
"statement.filter": ["block.filter", "block.object"],
"statement.filter.exp": ["exp"],
"statement.filter.type": ["input.type"],
"statement.obj": ["block.object"],
"statement.exp.literal.ident": ["input.ident"],
"statement.exp.literal.number": ["input.number"],
"statement.exp.op.add": ["exp.number", "exp.number"],
"statement.exp.op.substract": ["exp.number", "exp.number"],
"statement.exp.op.multiply": ["exp.number", "exp.number"],
"statement.exp.op.divide": ["exp.number", "exp.number"],
"statement.obj": ["block.element"],
"statement.prop": ["input.prop", "exp"],
"statement.select": ["block.select", "block.element"],
"statement.select.anchor": ["input.identanchor"],
"statement.select.atanchor": ["input.identanchor"],
"statement.select.exp": ["exp"],
"statement.select.type": ["input.type"],
}
};
var explists = {
"exp": ["#exp.array", "#exp.error", "#exp.identifier", "#exp.null", "#exp.number", "#exp.string", "#exp.vector"],
"exp.number": ["statement.exp.literal.number", "statement.exp.op.add", "statement.exp.op.substract", "statement.exp.op.multiply", "statement.exp.op.divide", "statement.exp.literal.ident"],
};
window.onload = function () {
lang = navigator.language.replace("-", "_");
@@ -95,7 +103,7 @@ function onAddButtonClick(event) {
function onAddExpButtonClick(event) {
cel = el = event.data;
generateAddExpList(event);
generateAddExpList(event, el.attr("key"));
}
function onAddButtonLiteralClick(event) {
@@ -123,7 +131,7 @@ var tblist = {
"tb-hide-add": "mode-hide-add",
"tb-hide-delete": "mode-hide-delete",
"tb-sort": "mode-sort",
}
};
function onToggleButtonClick(id, state) {
var cls = tblist[id];
if (state) tv.addClass(cls);
@@ -216,14 +224,20 @@ function generateAddList(event, items) {
popup(event, ul);
}
function generateAddExpList(event, items) {
function generateAddExpList(event, item) {
event.stopPropagation();
if (clist) clist.remove();
var ul = $("<ul></ul>").addClass("t-list t-exp-list");
for (var i in items) {
var item = items[i];
ul.append($("<li></li>").addClass("t-li").attr("key", item).text(msg("list." + item)).on("click", null, item, onAddItemClick));
}
(function addExpRecursive(it) {
var items = explists[it];
for (var i in items) {
var item = items[i];
if (item[0] == "#")
addExpRecursive(item.substring(1));
else
ul.append($("<li></li>").addClass("t-li").attr("key", item).text(msg("list." + item)).on("click", null, item, onAddItemClick));
}
})(item);
popup(event, ul);
}
@@ -349,10 +363,11 @@ function createExp(key) {
}
function createInput(key, target) {
var el = $("<input />").attr({
"type": "text",
"placeholder": msg(key + ".default")
});
var el = $("<input />").attr("placeholder", msg(key + ".default"));
switch (key) {
case "input.number": el.attr("type", "number"); break;
default: el.attr("type", "text"); break;
}
var r = $("<span></span>").attr({
"key": key,
"target": target.index()

View File

@@ -1,12 +1,13 @@
<!DOCTYPE HTML>
<head>
<meta charset="utf-8" />
<title>Skin Editor - Cosmo Resona</title>
<link type="text/css" rel="stylesheet" href="app.css"/>
<script type="text/javascript" src="jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="stretchy.min.js"></script>
<script type="text/javascript" src="array_util.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="messages/en_US.js"></script>
<script type="text/javascript" src="messages/en_US.js" charset="UTF-8"></script>
<script type="text/javascript" src="messages/zh_CN.js" charset="UTF-8"></script>
</head>
<body>

View File

@@ -1,71 +1,76 @@
messages["en_US"] = {
"block.filter": "If {}",
"block.select": "Select {}",
"input.comp.default": "component",
"input.comp.image": "image sprite",
"input.comp.polysec": "polygon sectional mesh",
"input.comp.rect": "colored rectangle",
"input.comp.scale3": "scale3 sprite",
"input.comp.text": "text",
"input.ident.default": "variable",
"input.prop.default": "property",
"input.prop.image.fit": "image sprite: scale mode",
"input.prop.image.frame": "image sprite: image name",
"input.prop.image.opacity": "image sprite: opacity",
"input.prop.polysec.body": "polygon sectional mesh: body image name",
"input.prop.polysec.head": "polygon sectional mesh: head image name",
"input.prop.polysec.shape": "polygon sectional mesh: section shape",
"input.prop.polysec.tail": "polygon sectional mesh: tail image name",
"input.prop.polysec.transparent": "polygon sectional mesh: transparent mode",
"input.prop.pos": "position",
"input.prop.rect.color": "colored rectangle: color",
"input.prop.rot": "rotation",
"input.prop.scale": "scale",
"input.prop.scale3.border": "scale3 sprite: unstretched area ratios",
"input.prop.sprite.bound": "sprite: secondary anchor position",
"input.prop.sprite.pivot": "sprite: anchor",
"input.prop.sprite.scale": "sprite: scale",
"input.prop.sprite.transparent": "sprite: transparent mode",
"input.prop.sprite.ui": "sprite: ui mode",
"input.prop.sprite.zindex": "sprite: layer order",
"input.prop.text.frames": "text: image mapping",
"input.prop.text.opacity": "text: opacity",
"input.prop.text.size": "text: font size",
"input.prop.text.spacing": "text: character spacing",
"input.prop.text.value": "text: content",
"input.type.chart": "chart",
"input.type.default": "element",
"input.type.group": "track group",
"input.type.note": "note",
"input.type.track": "track",
"list.statement.comp": "Attach a component",
"list.statement.define": "Define a variable",
"list.statement.filter": "Filter element",
"list.statement.filter.exp": "Filter expression",
"list.statement.filter.type": "Filter element type",
"list.statement.obj": "Create a container",
"list.statement.prop": "Set property",
"list.statement.select": "Select elements",
"list.statement.select.exp": "Filter expression",
"list.statement.select.type": "Filter element type",
"literal.block.filter": "If {statement.filter.exp} {statement.filter.type}",
"literal.block.select": "For each {statement.select.type?element} {statement.select.exp}",
"literal.statement.filter.exp": "{0}",
"literal.statement.filter.type": "it is a {0}",
"literal.statement.select.exp": "that {0}",
"literal.statement.select.type": "{0}",
"statement.comp": "with a {0}",
"statement.define": "Define {0} = {1}",
"statement.filter": "{0} {1}",
"statement.filter.exp": "it matches the expression {0}",
"statement.filter.type": "it is a {0}",
"statement.obj": "Create a container {0}",
"statement.prop": "Set its {0} to {1}",
"statement.select": "{0} {1}",
"statement.select.exp": "it matches the expression {0}",
"statement.select.type": "{0}",
"tool.debug": "Debug",
"tool.hideadd": "Hide Add",
"tool.hidedelete": "Hide Delete",
"tool.sort": "Sort",
};
"block.select": "Select {0}",
"input.comp.default": "component",
"input.comp.image": "image sprite",
"input.comp.polysec": "polygon sectional mesh",
"input.comp.rect": "colored rectangle",
"input.comp.scale3": "scale3 sprite",
"input.comp.text": "text",
"input.ident.default": "variable",
"input.identanchor.default": "anchor",
"input.number.default": "123",
"input.prop.default": "property",
"input.prop.image.fit": "image sprite: scale mode",
"input.prop.image.frame": "image sprite: image name",
"input.prop.image.opacity": "image sprite: opacity",
"input.prop.polysec.body": "polygon sectional mesh: body image name",
"input.prop.polysec.head": "polygon sectional mesh: head image name",
"input.prop.polysec.shape": "polygon sectional mesh: section shape",
"input.prop.polysec.tail": "polygon sectional mesh: tail image name",
"input.prop.polysec.transparent": "polygon sectional mesh: transparent mode",
"input.prop.pos": "position",
"input.prop.rect.color": "colored rectangle: color",
"input.prop.rot": "rotation",
"input.prop.scale": "scale",
"input.prop.scale3.border": "scale3 sprite: unstretched area ratios",
"input.prop.sprite.bound": "sprite: secondary anchor position",
"input.prop.sprite.pivot": "sprite: anchor",
"input.prop.sprite.scale": "sprite: scale",
"input.prop.sprite.transparent": "sprite: transparent mode",
"input.prop.sprite.ui": "sprite: ui mode",
"input.prop.sprite.zindex": "sprite: layer order",
"input.prop.text.frames": "text: image mapping",
"input.prop.text.opacity": "text: opacity",
"input.prop.text.size": "text: font size",
"input.prop.text.spacing": "text: character spacing",
"input.prop.text.value": "text: content",
"input.type.chart": "chart",
"input.type.default": "element",
"input.type.group": "track group",
"input.type.note": "note",
"input.type.track": "track",
"list.statement.comp": "Attach component",
"list.statement.define": "Define static variable",
"list.statement.exp.literal.ident": "Variable",
"list.statement.exp.literal.number": "Number",
"list.statement.exp.op.add": "a + b",
"list.statement.exp.op.divide": "a ÷ b",
"list.statement.exp.op.multiply": "a × b",
"list.statement.exp.op.substract": "a - b",
"list.statement.obj": "Create container",
"list.statement.prop": "Set property",
"list.statement.select": "Select elements",
"list.statement.select.anchor": "Select anchor",
"list.statement.select.atanchor": "Select at anchor",
"list.statement.select.exp": "Filter expression",
"list.statement.select.type": "Filter element type",
"statement.comp": "with a {0}",
"statement.define": "Define static {0} = {1}",
"statement.exp.literal.ident": "{0}",
"statement.exp.literal.number": "{0}",
"statement.exp.op.add": "{0} + {1}",
"statement.exp.op.divide": "{0} ÷ {1}",
"statement.exp.op.multiply": "{0} × {1}",
"statement.exp.op.substract": "{0} - {1}",
"statement.obj": "Create a container {0}",
"statement.prop": "Set its {0} to {1}",
"statement.select": "{0} {1}",
"statement.select.anchor": "Select its anchor {0}",
"statement.select.atanchor": "Select at its anchor {0}",
"statement.select.exp": "If it matches the expression {0}",
"statement.select.type": "If it is a {0}",
"tool.debug": "Debug",
"tool.hideadd": "Hide Add",
"tool.hidedelete": "Hide Delete",
"tool.sort": "Sort",
};

View File

@@ -1,6 +1,5 @@
messages["zh_CN"] = {
"block.filter": "如果 {}",
"block.select": "选择 {}",
"block.select": "选择 {0}",
"input.comp.default": "组件",
"input.comp.image": "图片",
"input.comp.polysec": "多边形截面网格",
@@ -8,6 +7,8 @@ messages["zh_CN"] = {
"input.comp.scale3": "三段拉伸图片",
"input.comp.text": "文字",
"input.ident.default": "变量",
"input.identanchor.default": "锚点",
"input.number.default": "123",
"input.prop.default": "属性",
"input.prop.image.fit": "图片:缩放模式",
"input.prop.image.frame": "图片:图片名",
@@ -39,33 +40,37 @@ messages["zh_CN"] = {
"input.type.note": "按键",
"input.type.track": "轨道",
"list.statement.comp": "附加组件",
"list.statement.define": "定义变量",
"list.statement.filter": "条件分歧",
"list.statement.filter.exp": "判断表达式",
"list.statement.filter.type": "判断元素类型",
"list.statement.define": "定义静态变量",
"list.statement.exp.literal.ident": "变量",
"list.statement.exp.literal.number": "数字",
"list.statement.exp.op.add": "a + b",
"list.statement.exp.op.divide": "a ÷ b",
"list.statement.exp.op.multiply": "a × b",
"list.statement.exp.op.substract": "a - b",
"list.statement.obj": "创建容器",
"list.statement.prop": "设置属性",
"list.statement.select": "选择元素",
"list.statement.select.anchor": "选择锚点",
"list.statement.select.atanchor": "选择位于锚点",
"list.statement.select.exp": "筛选表达式",
"list.statement.select.type": "筛选元素类型",
"literal.block.filter": "如果 {statement.filter.exp} {statement.filter.type}",
"literal.block.select": "对于每个 {statement.select.exp} {statement.select.type?元素}",
"literal.statement.filter.exp": "{0}",
"literal.statement.filter.type": "元素的类型为 {0}",
"literal.statement.select.exp": "{0} 的",
"literal.statement.select.type": "{0}",
"statement.comp": "创建一个 {0} 组件",
"statement.define": "定义变量 {0} = {1}",
"statement.filter": "{0} {1}",
"statement.filter.exp": "元素符合表达式 {0}",
"statement.filter.type": "元素的类型为 {0}",
"statement.define": "静态定义 {0} = {1}",
"statement.exp.literal.ident": "{0}",
"statement.exp.literal.number": "{0}",
"statement.exp.op.add": "{0} + {1}",
"statement.exp.op.divide": "{0} ÷ {1}",
"statement.exp.op.multiply": "{0} × {1}",
"statement.exp.op.substract": "{0} - {1}",
"statement.obj": "创建一个容器 {0}",
"statement.prop": "设置属性 {0} 为 {1}",
"statement.select": "{0} {1}",
"statement.select.exp": "元素符合表达式 {0}",
"statement.select.type": "元素的类型为 {0}",
"statement.select.anchor": "选择其 {0} 锚点",
"statement.select.atanchor": "选择位于其 {0} 锚点",
"statement.select.exp": "如果元素符合表达式 {0}",
"statement.select.type": "如果元素的类型为 {0}",
"tool.debug": "调试",
"tool.hideadd": "隐藏添加按钮",
"tool.hidedelete": "隐藏删除按钮",
"tool.sort": "排序",
};
};