diff --git a/Assets/Script/Lib/Config.tl b/Assets/Script/Lib/Config.tl index 78a94ce4e..dcd5252f5 100644 --- a/Assets/Script/Lib/Config.tl +++ b/Assets/Script/Lib/Config.tl @@ -19,7 +19,9 @@ return function(schema: string, ...: string): DoraConfig local insertValues: {string: any} = {} local updateValues: {string: any} = {} local deleteValues: {string} = {} + local loaded = false local function notify(event: Struct.RecordEvent, key: string, value: any) + assert(loaded, "Config should be loaded before updating") if event == "Modified" then if oldValues[key] == nil then insertValues[key] = value @@ -84,24 +86,35 @@ return function(schema: string, ...: string): DoraConfig ]]) end - rawset(conf as table, "loadAsync", function(self: DoraConfig) - local rows = DB:queryAsync("select name, value_num, value_str from " .. tableName) as {{string, number, string}} + local function initConfig(self: DoraConfig, rows: {{string, number, string}}) + local mt = getmetatable(self) as {string} + local fields = {} + for i = 1, #mt do + local fieldName = mt[i] + fields[fieldName] = true + end for i = 1, #rows do local key = rows[i][1] - local value: number | string = rows[i][2] or rows[i][3] - oldValues[key] = value - self[key] = value + if fields[key] then + local value: number | string = rows[i][2] or rows[i][3] + oldValues[key] = value + self[key] = value + else + print("Config key \"" .. key .. "\" is no longer exist") + end end + end + + rawset(conf as table, "loadAsync", function(self: DoraConfig) + local rows = DB:queryAsync("select name, value_num, value_str from " .. tableName) as {{string, number, string}} + loaded = true + initConfig(self, rows) end) rawset(conf as table, "load", function(self: DoraConfig) local rows = DB:query("select name, value_num, value_str from " .. tableName) as {{string, number, string}} - for i = 1, #rows do - local key = rows[i][1] - local value: number | string = rows[i][2] or rows[i][3] - oldValues[key] = value - self[key] = value - end + loaded = true + initConfig(self, rows) end) rawset(conf as table, "__notify", notify) diff --git a/Assets/Script/Test/TextInput.yue b/Assets/Script/Test/TextInput.yue index eb648f782..19c029c86 100644 --- a/Assets/Script/Test/TextInput.yue +++ b/Assets/Script/Test/TextInput.yue @@ -51,8 +51,9 @@ TextInput = Class ((args)-> (pos) <- \convertToWindowSpace Vec2 -label.x + label.width, 0 Keyboard\updateIMEPosHint pos startEditing = -> - \attachIME! - updateIMEPos! + if !@imeAttached + \attachIME! + updateIMEPos! .updateDisplayText = (text)=> textDisplay = text label.text = text diff --git a/Source/3rdParty/httplib/httplib.h b/Source/3rdParty/httplib/httplib.h index d6a608bcd..5c064dba8 100644 --- a/Source/3rdParty/httplib/httplib.h +++ b/Source/3rdParty/httplib/httplib.h @@ -8,7 +8,7 @@ #ifndef CPPHTTPLIB_HTTPLIB_H #define CPPHTTPLIB_HTTPLIB_H -#define CPPHTTPLIB_VERSION "0.15.1" +#define CPPHTTPLIB_VERSION "0.15.2" /* * Configuration @@ -2421,7 +2421,11 @@ inline bool is_valid_path(const std::string &path) { // Read component auto beg = i; while (i < path.size() && path[i] != '/') { - if (path[i] == '\0') { return false; } + if (path[i] == '\0') { + return false; + } else if (path[i] == '\\') { + return false; + } i++; } diff --git a/Source/3rdParty/yuescript/yue_ast.cpp b/Source/3rdParty/yuescript/yue_ast.cpp index c25f42d59..faa175da5 100644 --- a/Source/3rdParty/yuescript/yue_ast.cpp +++ b/Source/3rdParty/yuescript/yue_ast.cpp @@ -1405,15 +1405,8 @@ std::string UnaryExp_t::to_string(void* ud) const { } return line; } -std::string InDiscrete_t::to_string(void* ud) const { - str_list temp; - for (auto value : values.objects()) { - temp.emplace_back(value->to_string(ud)); - } - return '[' + join(temp, ", "sv) + (temp.size() == 1 ? ",]"s : "]"s); -} std::string In_t::to_string(void* ud) const { - return (not_ ? "not "s : ""s) + "in "s + item->to_string(ud); + return (not_ ? "not "s : ""s) + "in "s + value->to_string(ud); } std::string ExpListAssign_t::to_string(void* ud) const { if (action) { diff --git a/Source/3rdParty/yuescript/yue_ast.h b/Source/3rdParty/yuescript/yue_ast.h index fc07370b5..90dce7aa5 100644 --- a/Source/3rdParty/yuescript/yue_ast.h +++ b/Source/3rdParty/yuescript/yue_ast.h @@ -81,6 +81,7 @@ class In_t; class NormalDef_t; class SpreadListExp_t; class Comprehension_t; +class Value_t; } // namespace yue AST_LEAF(Num) @@ -445,16 +446,10 @@ AST_END(UnaryOperator, "unary_op"sv) AST_LEAF(NotIn) AST_END(NotIn, "not_in"sv) -AST_NODE(InDiscrete) - ast_ptr sep; - ast_list values; - AST_MEMBER(InDiscrete, &sep, &values) -AST_END(InDiscrete, "in_discrete"sv) - AST_NODE(In) ast_ptr not_; - ast_sel item; - AST_MEMBER(In, ¬_, &item) + ast_ptr value; + AST_MEMBER(In, ¬_, &value) AST_END(In, "in"sv) AST_NODE(Assignable) diff --git a/Source/3rdParty/yuescript/yue_compiler.cpp b/Source/3rdParty/yuescript/yue_compiler.cpp index ba74d9197..5cdbfda92 100644 --- a/Source/3rdParty/yuescript/yue_compiler.cpp +++ b/Source/3rdParty/yuescript/yue_compiler.cpp @@ -75,7 +75,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.21.6"sv; +const std::string_view version = "0.21.7"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1231,7 +1231,7 @@ class YueCompilerImpl { auto unary = static_cast(exp->pipeExprs.back()); BREAK_IF(unary->expos.size() != 1); BREAK_IF(!unary->inExp); - if (unary->inExp->item.is()) { + if (unary->inExp) { return unary; } auto value = static_cast(unary->expos.back()); @@ -5946,17 +5946,146 @@ class YueCompilerImpl { varName.clear(); } } - if (auto inExp = unary_exp->inExp->item.as()) { - str_list temp; - auto checkVar = singleVariableFrom(inExp, false); - if (usage == ExpUsage::Assignment) { - auto block = x->new_ptr(); + ast_ptr discrete; + auto inExp = unary_exp->inExp->value.get(); + BLOCK_START + auto sval = inExp->item.as(); + BREAK_IF(!sval); + if (auto table = sval->value.as()) { + discrete = inExp->new_ptr(); + for (ast_node* val : table->values.objects()) { + if (auto def = ast_cast(val)) { + if (def->defVal) { + discrete = nullptr; + break; + } else { + discrete->exprs.push_back(def->item); + } + } else if (ast_is(val)) { + discrete->exprs.push_back(val); + } else { + discrete = nullptr; + break; + } + } + } else if (auto comp = sval->value.as()) { + if (comp->items.size() != 2 || !ast_is(comp->items.back())) { + discrete = inExp->new_ptr(); + for (ast_node* val : comp->items.objects()) { + if (auto def = ast_cast(val)) { + if (def->defVal) { + discrete = nullptr; + break; + } else { + discrete->exprs.push_back(def->item); + } + } else { + discrete = nullptr; + break; + } + } + } + } + BLOCK_END + BLOCK_START + BREAK_IF(discrete); + str_list temp; + auto checkVar = singleVariableFrom(inExp, false); + if (usage == ExpUsage::Assignment) { + auto block = x->new_ptr(); + if (checkVar.empty() || !isLocal(checkVar)) { + checkVar = getUnusedName("_check_"sv); + auto assignment = assignmentFrom(toAst(checkVar, inExp), newExp(inExp, inExp), inExp); + auto stmt = x->new_ptr(); + stmt->content.set(assignment); + block->statements.push_back(stmt); + } + if (varName.empty()) { + auto newUnaryExp = x->new_ptr(); + newUnaryExp->ops.dup(unary_exp->ops); + newUnaryExp->expos.dup(unary_exp->expos); + auto exp = newExp(newUnaryExp, x); + varName = getUnusedName("_val_"sv); + auto assignExp = toAst(varName, x); + auto assignment = assignmentFrom(assignExp, exp, x); + auto stmt = x->new_ptr(); + stmt->content.set(assignment); + block->statements.push_back(stmt); + } + auto findVar = getUnusedName("_find_"); + auto itemVar = getUnusedName("_item_"); + _buf << findVar << "=false\n"sv; + _buf << "for "sv << itemVar << " in *"sv << checkVar << '\n'; + _buf << "\tif "sv << itemVar << "=="sv << varName << '\n'; + _buf << "\t\t"sv << findVar << "=true\n"sv; + _buf << "\t\tbreak\n"sv; + if (unary_exp->inExp->not_) { + _buf << "not "sv << findVar; + } else { + _buf << findVar; + } + auto blockStr = clearBuf(); + auto checkBlock = toAst(blockStr, inExp); + block->statements.dup(checkBlock->statements); + auto body = x->new_ptr(); + body->content.set(block); + auto doNode = x->new_ptr(); + doNode->body.set(body); + auto assign = x->new_ptr(); + auto simpleValue = x->new_ptr(); + simpleValue->value.set(doNode); + auto value = x->new_ptr(); + value->item.set(simpleValue); + assign->values.push_back(newExp(value, x)); + auto assignment = x->new_ptr(); + assignment->action.set(assign); + assignment->expList.set(assignList); + transformAssignment(assignment, temp); + out.push_back(join(temp)); + return; + } else { + auto arrayCheck = [&](bool exist) { + auto indexVar = getUnusedName("_index_"); + _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); + incIndentOffset(); + _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); + incIndentOffset(); + _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x); + decIndentOffset(); + _buf << indent() << "end"sv << nll(x); + decIndentOffset(); + _buf << indent() << "end"sv << nll(x); + _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x); + temp.push_back(clearBuf()); + }; + bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); + if (useShortCheck) { + if (usage == ExpUsage::Return) { + arrayCheck(!unary_exp->inExp->not_); + } else { + pushFunctionScope(); + pushAnonVarArg(); + pushScope(); + arrayCheck(true); + temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); + popScope(); + temp.push_back(indent() + anonFuncEnd() + ')'); + if (unary_exp->inExp->not_) { + temp.front().insert(0, "not "s); + } + popAnonVarArg(); + popFunctionScope(); + } + } else { + if (usage == ExpUsage::Closure) { + pushFunctionScope(); + pushAnonVarArg(); + pushScope(); + } if (checkVar.empty() || !isLocal(checkVar)) { checkVar = getUnusedName("_check_"sv); - auto assignment = assignmentFrom(toAst(checkVar, inExp), inExp, inExp); - auto stmt = x->new_ptr(); - stmt->content.set(assignment); - block->statements.push_back(stmt); + auto assignment = assignmentFrom(toAst(checkVar, inExp), newExp(inExp, inExp), inExp); + transformAssignment(assignment, temp); } if (varName.empty()) { auto newUnaryExp = x->new_ptr(); @@ -5966,114 +6095,26 @@ class YueCompilerImpl { varName = getUnusedName("_val_"sv); auto assignExp = toAst(varName, x); auto assignment = assignmentFrom(assignExp, exp, x); - auto stmt = x->new_ptr(); - stmt->content.set(assignment); - block->statements.push_back(stmt); - } - auto findVar = getUnusedName("_find_"); - auto itemVar = getUnusedName("_item_"); - _buf << findVar << "=false\n"sv; - _buf << "for "sv << itemVar << " in *"sv << checkVar << '\n'; - _buf << "\tif "sv << itemVar << "=="sv << varName << '\n'; - _buf << "\t\t"sv << findVar << "=true\n"sv; - _buf << "\t\tbreak\n"sv; - if (unary_exp->inExp->not_) { - _buf << "not "sv << findVar; - } else { - _buf << findVar; + transformAssignment(assignment, temp); } - auto blockStr = clearBuf(); - auto checkBlock = toAst(blockStr, inExp); - block->statements.dup(checkBlock->statements); - auto body = x->new_ptr(); - body->content.set(block); - auto doNode = x->new_ptr(); - doNode->body.set(body); - auto assign = x->new_ptr(); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(doNode); - auto value = x->new_ptr(); - value->item.set(simpleValue); - assign->values.push_back(newExp(value, x)); - auto assignment = x->new_ptr(); - assignment->action.set(assign); - assignment->expList.set(assignList); - transformAssignment(assignment, temp); - out.push_back(join(temp)); - return; - } else { - auto arrayCheck = [&](bool exist) { - auto indexVar = getUnusedName("_index_"); - _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); - incIndentOffset(); - _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); - incIndentOffset(); - _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x); - decIndentOffset(); - _buf << indent() << "end"sv << nll(x); - decIndentOffset(); - _buf << indent() << "end"sv << nll(x); - _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x); - temp.push_back(clearBuf()); - }; - bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); - if (useShortCheck) { - if (usage == ExpUsage::Return) { - arrayCheck(!unary_exp->inExp->not_); - } else { - pushFunctionScope(); - pushAnonVarArg(); - pushScope(); - arrayCheck(true); - temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); - popScope(); - temp.push_back(indent() + anonFuncEnd() + ')'); - if (unary_exp->inExp->not_) { - temp.front().insert(0, "not "s); - } - popAnonVarArg(); - popFunctionScope(); - } + if (usage == ExpUsage::Return) { + arrayCheck(!unary_exp->inExp->not_); } else { - if (usage == ExpUsage::Closure) { - pushFunctionScope(); - pushAnonVarArg(); - pushScope(); - } - if (checkVar.empty() || !isLocal(checkVar)) { - checkVar = getUnusedName("_check_"sv); - auto assignment = assignmentFrom(toAst(checkVar, inExp), inExp, inExp); - transformAssignment(assignment, temp); - } - if (varName.empty()) { - auto newUnaryExp = x->new_ptr(); - newUnaryExp->ops.dup(unary_exp->ops); - newUnaryExp->expos.dup(unary_exp->expos); - auto exp = newExp(newUnaryExp, x); - varName = getUnusedName("_val_"sv); - auto assignExp = toAst(varName, x); - auto assignment = assignmentFrom(assignExp, exp, x); - transformAssignment(assignment, temp); - } - if (usage == ExpUsage::Return) { - arrayCheck(!unary_exp->inExp->not_); - } else { - arrayCheck(!unary_exp->inExp->not_); - temp.push_front(anonFuncStart() + nll(x)); - popScope(); - temp.push_back(indent() + anonFuncEnd()); - popAnonVarArg(); - popFunctionScope(); - } + arrayCheck(!unary_exp->inExp->not_); + temp.push_front(anonFuncStart() + nll(x)); + popScope(); + temp.push_back(indent() + anonFuncEnd()); + popAnonVarArg(); + popFunctionScope(); } - out.push_back(join(temp)); - return; } + out.push_back(join(temp)); + return; } - auto discrete = unary_exp->inExp->item.to(); - if (usage == ExpUsage::Closure && discrete->values.size() == 1) { + BLOCK_END + if (usage == ExpUsage::Closure && discrete->exprs.size() == 1) { str_list tmp; - transformExp(static_cast(discrete->values.front()), tmp, ExpUsage::Closure); + transformExp(static_cast(discrete->exprs.front()), tmp, ExpUsage::Closure); tmp.push_back(" == "s); auto newUnaryExp = x->new_ptr(); newUnaryExp->ops.dup(unary_exp->ops); @@ -6108,7 +6149,7 @@ class YueCompilerImpl { transformAssignment(assignment, temp); str_list tmp; - for (auto exp : discrete->values.objects()) { + for (auto exp : discrete->exprs.objects()) { transformExp(static_cast(exp), tmp, ExpUsage::Closure); } if (usage == ExpUsage::Assignment) { @@ -6148,9 +6189,16 @@ class YueCompilerImpl { } } else { str_list tmp; - for (auto exp : discrete->values.objects()) { + for (auto exp : discrete->exprs.objects()) { transformExp(static_cast(exp), tmp, ExpUsage::Closure); } + if (usage == ExpUsage::Assignment) { + str_list tmpList; + transformExp(static_cast(assignList->exprs.front()), tmpList, ExpUsage::Closure); + _buf << indent() << tmpList.back() << " = "sv; + } else if (usage == ExpUsage::Return) { + _buf << indent() << "return "sv; + } if (unary_exp->inExp->not_) { _buf << "not "sv; } @@ -6162,6 +6210,9 @@ class YueCompilerImpl { } } _buf << ')'; + if (usage == ExpUsage::Assignment || usage == ExpUsage::Return) { + _buf << nll(discrete); + } out.push_back(clearBuf()); } return; diff --git a/Source/3rdParty/yuescript/yue_parser.cpp b/Source/3rdParty/yuescript/yue_parser.cpp index 6aa0954c3..d13897965 100644 --- a/Source/3rdParty/yuescript/yue_parser.cpp +++ b/Source/3rdParty/yuescript/yue_parser.cpp @@ -519,10 +519,7 @@ YueParser::YueParser() { expo_exp = Value >> *(space >> expo_value); NotIn = true_(); - InDiscrete = - '[' >> Seperator >> space >> exp_not_tab >> (+(space >> ',' >> space >> exp_not_tab) | space >> ',') >> space >> ']' | - '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab | space >> ',') >> space >> '}'; - In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp); + In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (and_(key("not")) >> confusing_unary_not_error | Value); UnaryOperator = '-' >> not_(set(">=") | space_one) | diff --git a/Source/3rdParty/yuescript/yue_parser.h b/Source/3rdParty/yuescript/yue_parser.h index 213d33e5d..39b7cce4f 100644 --- a/Source/3rdParty/yuescript/yue_parser.h +++ b/Source/3rdParty/yuescript/yue_parser.h @@ -402,7 +402,6 @@ class YueParser { AST_RULE(UnaryValue); AST_RULE(UnaryExp); AST_RULE(NotIn); - AST_RULE(InDiscrete); AST_RULE(In); AST_RULE(ExpListAssign); AST_RULE(IfLine); diff --git a/Source/Input/Keyboard.cpp b/Source/Input/Keyboard.cpp index c9a5cb650..08bed4c75 100644 --- a/Source/Input/Keyboard.cpp +++ b/Source/Input/Keyboard.cpp @@ -231,11 +231,6 @@ void Keyboard::updateIMEPosHint(const Vec2& winPos) { void Keyboard::handleEvent(const SDL_Event& event) { switch (event.type) { - case SDL_MOUSEBUTTONDOWN: - case SDL_FINGERDOWN: { - detachIME(); - break; - } case SDL_KEYDOWN: { Slice name; bool oldDown; diff --git a/Source/Platformer/Unit.cpp b/Source/Platformer/Unit.cpp index c9f267c5b..e20095551 100644 --- a/Source/Platformer/Unit.cpp +++ b/Source/Platformer/Unit.cpp @@ -347,6 +347,7 @@ bool Unit::start(String name) { void Unit::stop() { if (_currentAction && _currentAction->isDoing()) { _currentAction->stop(); + _currentAction->_status = Behavior::Status::Success; _currentAction = nullptr; } }