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

View File

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

View File

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

View File

@@ -1,71 +1,76 @@
messages["en_US"] = { messages["en_US"] = {
"block.filter": "If {}", "block.select": "Select {0}",
"block.select": "Select {}", "input.comp.default": "component",
"input.comp.default": "component", "input.comp.image": "image sprite",
"input.comp.image": "image sprite", "input.comp.polysec": "polygon sectional mesh",
"input.comp.polysec": "polygon sectional mesh", "input.comp.rect": "colored rectangle",
"input.comp.rect": "colored rectangle", "input.comp.scale3": "scale3 sprite",
"input.comp.scale3": "scale3 sprite", "input.comp.text": "text",
"input.comp.text": "text", "input.ident.default": "variable",
"input.ident.default": "variable", "input.identanchor.default": "anchor",
"input.prop.default": "property", "input.number.default": "123",
"input.prop.image.fit": "image sprite: scale mode", "input.prop.default": "property",
"input.prop.image.frame": "image sprite: image name", "input.prop.image.fit": "image sprite: scale mode",
"input.prop.image.opacity": "image sprite: opacity", "input.prop.image.frame": "image sprite: image name",
"input.prop.polysec.body": "polygon sectional mesh: body image name", "input.prop.image.opacity": "image sprite: opacity",
"input.prop.polysec.head": "polygon sectional mesh: head image name", "input.prop.polysec.body": "polygon sectional mesh: body image name",
"input.prop.polysec.shape": "polygon sectional mesh: section shape", "input.prop.polysec.head": "polygon sectional mesh: head image name",
"input.prop.polysec.tail": "polygon sectional mesh: tail image name", "input.prop.polysec.shape": "polygon sectional mesh: section shape",
"input.prop.polysec.transparent": "polygon sectional mesh: transparent mode", "input.prop.polysec.tail": "polygon sectional mesh: tail image name",
"input.prop.pos": "position", "input.prop.polysec.transparent": "polygon sectional mesh: transparent mode",
"input.prop.rect.color": "colored rectangle: color", "input.prop.pos": "position",
"input.prop.rot": "rotation", "input.prop.rect.color": "colored rectangle: color",
"input.prop.scale": "scale", "input.prop.rot": "rotation",
"input.prop.scale3.border": "scale3 sprite: unstretched area ratios", "input.prop.scale": "scale",
"input.prop.sprite.bound": "sprite: secondary anchor position", "input.prop.scale3.border": "scale3 sprite: unstretched area ratios",
"input.prop.sprite.pivot": "sprite: anchor", "input.prop.sprite.bound": "sprite: secondary anchor position",
"input.prop.sprite.scale": "sprite: scale", "input.prop.sprite.pivot": "sprite: anchor",
"input.prop.sprite.transparent": "sprite: transparent mode", "input.prop.sprite.scale": "sprite: scale",
"input.prop.sprite.ui": "sprite: ui mode", "input.prop.sprite.transparent": "sprite: transparent mode",
"input.prop.sprite.zindex": "sprite: layer order", "input.prop.sprite.ui": "sprite: ui mode",
"input.prop.text.frames": "text: image mapping", "input.prop.sprite.zindex": "sprite: layer order",
"input.prop.text.opacity": "text: opacity", "input.prop.text.frames": "text: image mapping",
"input.prop.text.size": "text: font size", "input.prop.text.opacity": "text: opacity",
"input.prop.text.spacing": "text: character spacing", "input.prop.text.size": "text: font size",
"input.prop.text.value": "text: content", "input.prop.text.spacing": "text: character spacing",
"input.type.chart": "chart", "input.prop.text.value": "text: content",
"input.type.default": "element", "input.type.chart": "chart",
"input.type.group": "track group", "input.type.default": "element",
"input.type.note": "note", "input.type.group": "track group",
"input.type.track": "track", "input.type.note": "note",
"list.statement.comp": "Attach a component", "input.type.track": "track",
"list.statement.define": "Define a variable", "list.statement.comp": "Attach component",
"list.statement.filter": "Filter element", "list.statement.define": "Define static variable",
"list.statement.filter.exp": "Filter expression", "list.statement.exp.literal.ident": "Variable",
"list.statement.filter.type": "Filter element type", "list.statement.exp.literal.number": "Number",
"list.statement.obj": "Create a container", "list.statement.exp.op.add": "a + b",
"list.statement.prop": "Set property", "list.statement.exp.op.divide": "a ÷ b",
"list.statement.select": "Select elements", "list.statement.exp.op.multiply": "a × b",
"list.statement.select.exp": "Filter expression", "list.statement.exp.op.substract": "a - b",
"list.statement.select.type": "Filter element type", "list.statement.obj": "Create container",
"literal.block.filter": "If {statement.filter.exp} {statement.filter.type}", "list.statement.prop": "Set property",
"literal.block.select": "For each {statement.select.type?element} {statement.select.exp}", "list.statement.select": "Select elements",
"literal.statement.filter.exp": "{0}", "list.statement.select.anchor": "Select anchor",
"literal.statement.filter.type": "it is a {0}", "list.statement.select.atanchor": "Select at anchor",
"literal.statement.select.exp": "that {0}", "list.statement.select.exp": "Filter expression",
"literal.statement.select.type": "{0}", "list.statement.select.type": "Filter element type",
"statement.comp": "with a {0}", "statement.comp": "with a {0}",
"statement.define": "Define {0} = {1}", "statement.define": "Define static {0} = {1}",
"statement.filter": "{0} {1}", "statement.exp.literal.ident": "{0}",
"statement.filter.exp": "it matches the expression {0}", "statement.exp.literal.number": "{0}",
"statement.filter.type": "it is a {0}", "statement.exp.op.add": "{0} + {1}",
"statement.obj": "Create a container {0}", "statement.exp.op.divide": "{0} ÷ {1}",
"statement.prop": "Set its {0} to {1}", "statement.exp.op.multiply": "{0} × {1}",
"statement.select": "{0} {1}", "statement.exp.op.substract": "{0} - {1}",
"statement.select.exp": "it matches the expression {0}", "statement.obj": "Create a container {0}",
"statement.select.type": "{0}", "statement.prop": "Set its {0} to {1}",
"tool.debug": "Debug", "statement.select": "{0} {1}",
"tool.hideadd": "Hide Add", "statement.select.anchor": "Select its anchor {0}",
"tool.hidedelete": "Hide Delete", "statement.select.atanchor": "Select at its anchor {0}",
"tool.sort": "Sort", "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"] = { messages["zh_CN"] = {
"block.filter": "如果 {}", "block.select": "选择 {0}",
"block.select": "选择 {}",
"input.comp.default": "组件", "input.comp.default": "组件",
"input.comp.image": "图片", "input.comp.image": "图片",
"input.comp.polysec": "多边形截面网格", "input.comp.polysec": "多边形截面网格",
@@ -8,6 +7,8 @@ messages["zh_CN"] = {
"input.comp.scale3": "三段拉伸图片", "input.comp.scale3": "三段拉伸图片",
"input.comp.text": "文字", "input.comp.text": "文字",
"input.ident.default": "变量", "input.ident.default": "变量",
"input.identanchor.default": "锚点",
"input.number.default": "123",
"input.prop.default": "属性", "input.prop.default": "属性",
"input.prop.image.fit": "图片:缩放模式", "input.prop.image.fit": "图片:缩放模式",
"input.prop.image.frame": "图片:图片名", "input.prop.image.frame": "图片:图片名",
@@ -39,33 +40,37 @@ messages["zh_CN"] = {
"input.type.note": "按键", "input.type.note": "按键",
"input.type.track": "轨道", "input.type.track": "轨道",
"list.statement.comp": "附加组件", "list.statement.comp": "附加组件",
"list.statement.define": "定义变量", "list.statement.define": "定义静态变量",
"list.statement.filter": "条件分歧", "list.statement.exp.literal.ident": "变量",
"list.statement.filter.exp": "判断表达式", "list.statement.exp.literal.number": "数字",
"list.statement.filter.type": "判断元素类型", "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.obj": "创建容器",
"list.statement.prop": "设置属性", "list.statement.prop": "设置属性",
"list.statement.select": "选择元素", "list.statement.select": "选择元素",
"list.statement.select.anchor": "选择锚点",
"list.statement.select.atanchor": "选择位于锚点",
"list.statement.select.exp": "筛选表达式", "list.statement.select.exp": "筛选表达式",
"list.statement.select.type": "筛选元素类型", "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.comp": "创建一个 {0} 组件",
"statement.define": "定义变量 {0} = {1}", "statement.define": "静态定义 {0} = {1}",
"statement.filter": "{0} {1}", "statement.exp.literal.ident": "{0}",
"statement.filter.exp": "元素符合表达式 {0}", "statement.exp.literal.number": "{0}",
"statement.filter.type": "元素的类型为 {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.obj": "创建一个容器 {0}",
"statement.prop": "设置属性 {0} 为 {1}", "statement.prop": "设置属性 {0} 为 {1}",
"statement.select": "{0} {1}", "statement.select": "{0} {1}",
"statement.select.exp": "元素符合表达式 {0}", "statement.select.anchor": "选择其 {0} 锚点",
"statement.select.type": "元素的类型为 {0}", "statement.select.atanchor": "选择位于其 {0} 锚点",
"statement.select.exp": "如果元素符合表达式 {0}",
"statement.select.type": "如果元素的类型为 {0}",
"tool.debug": "调试", "tool.debug": "调试",
"tool.hideadd": "隐藏添加按钮", "tool.hideadd": "隐藏添加按钮",
"tool.hidedelete": "隐藏删除按钮", "tool.hidedelete": "隐藏删除按钮",
"tool.sort": "排序", "tool.sort": "排序",
}; };