summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/physics/body_sw.cpp1
-rw-r--r--servers/physics_2d/body_2d_sw.cpp30
-rw-r--r--servers/physics_2d/body_2d_sw.h1
-rw-r--r--servers/visual/shader_language.cpp195
-rw-r--r--servers/visual/shader_language.h13
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) {}
};