diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/physics/body_sw.cpp | 1 | ||||
-rw-r--r-- | servers/physics_2d/body_2d_sw.cpp | 30 | ||||
-rw-r--r-- | servers/physics_2d/body_2d_sw.h | 1 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 195 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 13 |
5 files changed, 226 insertions, 14 deletions
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 172a2a3429..a3bb581cb5 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -266,6 +266,7 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _set_static(false); + angular_velocity = Vector3(); } break; } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index b9ebd30021..6ba159ca0a 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -47,8 +47,10 @@ void Body2DSW::update_inertias() { case Physics2DServer::BODY_MODE_RIGID: { - if (user_inertia) break; - + if (user_inertia) { + _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; + break; + } //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet) real_t total_area = 0; @@ -57,7 +59,7 @@ void Body2DSW::update_inertias() { total_area += get_shape_aabb(i).get_area(); } - real_t _inertia = 0; + inertia = 0; for (int i = 0; i < get_shape_count(); i++) { @@ -73,15 +75,10 @@ void Body2DSW::update_inertias() { Transform2D mtx = get_shape_transform(i); Vector2 scale = mtx.get_scale(); - _inertia += shape->get_moment_of_inertia(mass, scale) + mass * mtx.get_origin().length_squared(); - //Rect2 ab = get_shape_aabb(i); - //_inertia+=mass*ab.size.dot(ab.size)/12.0f; + inertia += shape->get_moment_of_inertia(mass, scale) + mass * mtx.get_origin().length_squared(); } - if (_inertia != 0) - _inv_inertia = 1.0 / _inertia; - else - _inv_inertia = 0.0; //wathever + _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; if (mass) _inv_mass = 1.0 / mass; @@ -160,6 +157,7 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) _update_inertia(); } else { user_inertia = true; + inertia = p_value; _inv_inertia = 1.0 / p_value; } } break; @@ -194,7 +192,7 @@ real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { return mass; } case Physics2DServer::BODY_PARAM_INERTIA: { - return _inv_inertia == 0 ? 0 : 1.0 / _inv_inertia; + return inertia; } case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; @@ -226,6 +224,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { _set_inv_transform(get_transform().affine_inverse()); _inv_mass = 0; + _inv_inertia = 0; _set_static(p_mode == Physics2DServer::BODY_MODE_STATIC); set_active(p_mode == Physics2DServer::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity = Vector2(); @@ -237,17 +236,21 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { case Physics2DServer::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; + _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; _set_static(false); } break; case Physics2DServer::BODY_MODE_CHARACTER: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; + _inv_inertia = 0; _set_static(false); + angular_velocity = 0; } break; } - - _update_inertia(); + if (p_mode == Physics2DServer::BODY_MODE_RIGID && _inv_inertia == 0) { + _update_inertia(); + } /* if (get_space()) _update_queries(); @@ -668,6 +671,7 @@ Body2DSW::Body2DSW() : angular_velocity = 0; biased_angular_velocity = 0; mass = 1; + inertia = 0; user_inertia = false; _inv_inertia = 0; _inv_mass = 1; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 8c64dc9230..5df184c894 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -52,6 +52,7 @@ class Body2DSW : public CollisionObject2DSW { real_t gravity_scale; real_t mass; + real_t inertia; real_t bounce; real_t friction; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 1dd6699851..e9d85c7eb0 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -283,6 +283,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_CF_DO, "do" }, { TK_CF_SWITCH, "switch" }, { TK_CF_CASE, "case" }, + { TK_CF_DEFAULT, "default" }, { TK_CF_BREAK, "break" }, { TK_CF_CONTINUE, "continue" }, { TK_CF_RETURN, "return" }, @@ -3778,6 +3779,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui TkPos pos = _get_tkpos(); Token tk = _get_token(); + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) { + if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) { + _set_error("Switch may contains only case and default blocks"); + return ERR_PARSE_ERROR; + } + } + if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block if (p_just_one) { _set_error("Unexpected '}'"); @@ -4132,6 +4141,183 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else { _set_tkpos(pos); //rollback } + } else if (tk.type == TK_CF_SWITCH) { + // switch() {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after switch"); + return ERR_PARSE_ERROR; + } + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_SWITCH; + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + if (n->get_datatype() != TYPE_INT) { + _set_error("Expected integer expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' after switch statement"); + return ERR_PARSE_ERROR; + } + BlockNode *switch_block = alloc_node<BlockNode>(); + switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH; + switch_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(switch_block); + p_block->statements.push_back(cf); + + int prev_type = TK_CF_CASE; + while (true) { // Go-through multiple cases. + + if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) { + return ERR_PARSE_ERROR; + } + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) { + if (prev_type == TK_CF_DEFAULT) { + if (tk.type == TK_CF_CASE) { + _set_error("Cases must be defined before default case."); + return ERR_PARSE_ERROR; + } else if (prev_type == TK_CF_DEFAULT) { + _set_error("Default case must be defined only once."); + return ERR_PARSE_ERROR; + } + } + prev_type = tk.type; + _set_tkpos(pos); + continue; + } else { + Set<int> constants; + for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. + ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; + if (flow) { + if (flow->flow_op == FLOW_OP_CASE) { + ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]); + if (!n2) { + return ERR_PARSE_ERROR; + } + if (n2->values.empty()) { + return ERR_PARSE_ERROR; + } + if (constants.has(n2->values[0].sint)) { + _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); + return ERR_PARSE_ERROR; + } + constants.insert(n2->values[0].sint); + } else if (flow->flow_op == FLOW_OP_DEFAULT) { + continue; + } else { + return ERR_PARSE_ERROR; + } + } else { + return ERR_PARSE_ERROR; + } + } + break; + } + } + + } else if (tk.type == TK_CF_CASE) { + // case x : break; | return; + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("case must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + int sign = 1; + + if (tk.type == TK_OP_SUB) { + sign = -1; + tk = _get_token(); + } + + if (tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + int constant = (int)tk.constant * sign; + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_CASE; + + ConstantNode *n = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.sint = constant; + n->values.push_back(v); + n->datatype = TYPE_INT; + + BlockNode *case_block = alloc_node<BlockNode>(); + case_block->block_type = BlockNode::BLOCK_TYPE_CASE; + case_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(case_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(case_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + + } else if (tk.type == TK_CF_DEFAULT) { + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("default must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_DEFAULT; + + BlockNode *default_block = alloc_node<BlockNode>(); + default_block->block_type = BlockNode::BLOCK_TYPE_DEFAULT; + default_block->parent_block = p_block; + cf->blocks.push_back(default_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(default_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + } else if (tk.type == TK_CF_DO || tk.type == TK_CF_WHILE) { // do {} while() // while() {} @@ -4299,6 +4485,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } p_block->statements.push_back(flow); + if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } } else if (tk.type == TK_CF_DISCARD) { //check return type @@ -4345,9 +4534,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } p_block->statements.push_back(flow); + if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } + } else if (tk.type == TK_CF_CONTINUE) { - if (!p_can_break) { + if (!p_can_continue) { //all is good _set_error("Continuing is not allowed here"); } diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 36c691c3ae..b71788513e 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -125,6 +125,7 @@ public: TK_CF_DO, TK_CF_SWITCH, TK_CF_CASE, + TK_CF_DEFAULT, TK_CF_BREAK, TK_CF_CONTINUE, TK_CF_RETURN, @@ -266,6 +267,8 @@ public: FLOW_OP_DO, FLOW_OP_BREAK, FLOW_OP_SWITCH, + FLOW_OP_CASE, + FLOW_OP_DEFAULT, FLOW_OP_CONTINUE, FLOW_OP_DISCARD }; @@ -420,6 +423,15 @@ public: FunctionNode *parent_function; BlockNode *parent_block; + enum BlockType { + BLOCK_TYPE_STANDART, + BLOCK_TYPE_SWITCH, + BLOCK_TYPE_CASE, + BLOCK_TYPE_DEFAULT, + }; + + int block_type; + struct Variable { DataType type; DataPrecision precision; @@ -436,6 +448,7 @@ public: Node(TYPE_BLOCK), parent_function(NULL), parent_block(NULL), + block_type(BLOCK_TYPE_STANDART), single_statement(false) {} }; |