diff options
Diffstat (limited to 'modules')
33 files changed, 478 insertions, 193 deletions
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp index 6b5438c60f..ecacce0bee 100644 --- a/modules/bullet/cone_twist_joint_bullet.cpp +++ b/modules/bullet/cone_twist_joint_bullet.cpp @@ -83,7 +83,9 @@ void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param, coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value); break; default: - WARN_PRINT("This parameter is not supported by Bullet engine"); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED + break; } } @@ -100,7 +102,8 @@ real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_para case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: return coneConstraint->getRelaxationFactor(); default: - WARN_PRINT("This parameter is not supported by Bullet engine"); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED; return 0; } } diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp index 6275a0d2ed..a36f1123bc 100644 --- a/modules/bullet/generic_6dof_joint_bullet.cpp +++ b/modules/bullet/generic_6dof_joint_bullet.cpp @@ -153,7 +153,9 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value; break; default: - WARN_PRINT("This parameter is not supported"); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED + break; } } @@ -181,8 +183,9 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce; default: - WARN_PRINT("This parameter is not supported"); - return 0.; + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED; + return 0; } } @@ -213,8 +216,9 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag]; break; default: - WARN_PRINT("This flag is not supported by Bullet engine"); - return; + ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated"); + WARN_DEPRECATED + break; } } diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp index 07fde6efb9..86c6a632cd 100644 --- a/modules/bullet/hinge_joint_bullet.cpp +++ b/modules/bullet/hinge_joint_bullet.cpp @@ -95,11 +95,6 @@ real_t HingeJointBullet::get_hinge_angle() { void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::HINGE_JOINT_BIAS: - if (0 < p_value) { - WARN_PRINTS("HingeJoint doesn't support bias in the Bullet backend, so it's always 0."); - } - break; case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; @@ -122,7 +117,9 @@ void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t hingeConstraint->setMaxMotorImpulse(p_value); break; default: - WARN_PRINTS("HingeJoint doesn't support this parameter in the Bullet backend: " + itos(p_param) + ", value: " + itos(p_value)); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED + break; } } @@ -146,7 +143,8 @@ real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: return hingeConstraint->getMaxMotorImpulse(); default: - WARN_PRINTS("HingeJoint doesn't support this parameter in the Bullet backend: " + itos(p_param)); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED; return 0; } } diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp index c4e5b8cdbe..183a7e75b9 100644 --- a/modules/bullet/pin_joint_bullet.cpp +++ b/modules/bullet/pin_joint_bullet.cpp @@ -85,7 +85,8 @@ real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const { case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: return p2pConstraint->m_setting.m_impulseClamp; default: - WARN_PRINTS("This get parameter is not supported"); + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED return 0; } } diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index b5329bc347..4a11bec5af 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -178,7 +178,9 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002); if (btResult.hasHit()) { - p_closest_safe = p_closest_unsafe = btResult.m_closestHitFraction; + const btScalar l = bt_motion.length(); + p_closest_unsafe = btResult.m_closestHitFraction; + p_closest_safe = MAX(p_closest_unsafe - (1 - ((l - 0.01) / l)), 0); if (r_info) { if (btCollisionObject::CO_RIGID_BODY == btResult.m_hitCollisionObject->getInternalType()) { B_TO_G(static_cast<const btRigidBody *>(btResult.m_hitCollisionObject)->getVelocityInLocalPoint(btResult.m_hitPointWorld), r_info->linear_velocity); diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index 3a371c8597..af92861352 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -247,8 +247,8 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressS } dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift; - w >>= 1; - h >>= 1; + w = MAX(w / 2, 1); + h = MAX(h / 2, 1); } if (num_job_threads > 0) { diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index e05bc7d591..33d9c011f2 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -126,7 +126,10 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco GDScriptLanguage::singleton->lock->unlock(); #endif - ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing + if (r_error.error != Variant::CallError::CALL_OK) { + memdelete(instance); + ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing + } } //@TODO make thread safe @@ -719,22 +722,36 @@ Error GDScript::load_byte_code(const String &p_path) { FileAccess *fa = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!fa, ERR_CANT_OPEN); + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); ERR_FAIL_COND_V(!fae, ERR_CANT_OPEN); + Vector<uint8_t> key; key.resize(32); for (int i = 0; i < key.size(); i++) { key.write[i] = script_encryption_key[i]; } + Error err = fae->open_and_parse(fa, key, FileAccessEncrypted::MODE_READ); - ERR_FAIL_COND_V(err, err); + + if (err) { + fa->close(); + memdelete(fa); + memdelete(fae); + + ERR_FAIL_COND_V(err, err); + } + bytecode.resize(fae->get_len()); fae->get_buffer(bytecode.ptrw(), bytecode.size()); + fae->close(); memdelete(fae); + } else { bytecode = FileAccess::get_file_as_array(p_path); } + ERR_FAIL_COND_V(bytecode.size() == 0, ERR_PARSE_ERROR); path = p_path; @@ -2097,7 +2114,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori Error err = script->load_byte_code(p_path); if (err != OK) { - + memdelete(script); ERR_FAIL_COND_V(err != OK, RES()); } @@ -2105,7 +2122,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori Error err = script->load_source_code(p_path); if (err != OK) { - + memdelete(script); ERR_FAIL_COND_V(err != OK, RES()); } @@ -2120,6 +2137,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori return scriptres; } + void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gd"); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 1403184557..006fbece53 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1253,6 +1253,25 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter) } break; + case GDScriptParser::OperatorNode::OP_IS_BUILTIN: { + ERR_FAIL_COND_V(on->arguments.size() != 2, false); + ERR_FAIL_COND_V(on->arguments[1]->type != GDScriptParser::Node::TYPE_TYPE, false); + + int slevel = p_stack_level; + + int src_address_a = _parse_expression(codegen, on->arguments[0], slevel); + if (src_address_a < 0) + return -1; + + if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) + slevel++; //uses stack for return, increase stack + + const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(on->arguments[1]); + + codegen.opcodes.push_back(GDScriptFunction::OPCODE_IS_BUILTIN); // perform operator + codegen.opcodes.push_back(src_address_a); // argument 1 + codegen.opcodes.push_back((int)tn->vtype); // argument 2 (unary only takes one parameter) + } break; default: { ERR_EXPLAIN("Bug in bytecode compiler, unexpected operator #" + itos(on->op) + " in parse tree while parsing expression."); @@ -1322,6 +1341,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo int ret = _parse_expression(codegen, op, p_stack_level); if (ret < 0) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1341,6 +1362,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo // compile the condition int ret = _parse_expression(codegen, branch.compiled_pattern, p_stack_level); if (ret < 0) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1353,6 +1376,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr); if (err) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1364,6 +1389,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size(); + memdelete(id); + memdelete(op); + } break; case GDScriptParser::ControlFlowNode::CF_IF: { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 30400f01e9..d3068fb6d0 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -63,8 +63,8 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str String _template = "extends %BASE%\n" "\n" "# Declare member variables here. Examples:\n" - "# var a %INT_TYPE%= 2\n" - "# var b %STRING_TYPE%= \"text\"\n" + "# var a%INT_TYPE% = 2\n" + "# var b%STRING_TYPE% = \"text\"\n" "\n" "# Called when the node enters the scene tree for the first time.\n" "func _ready()%VOID_RETURN%:\n" @@ -76,9 +76,9 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str #ifdef TOOLS_ENABLED if (EDITOR_DEF("text_editor/completion/add_type_hints", false)) { - _template = _template.replace("%INT_TYPE%", ": int "); - _template = _template.replace("%STRING_TYPE%", ": String "); - _template = _template.replace("%FLOAT_TYPE%", " : float"); + _template = _template.replace("%INT_TYPE%", ": int"); + _template = _template.replace("%STRING_TYPE%", ": String"); + _template = _template.replace("%FLOAT_TYPE%", ": float"); _template = _template.replace("%VOID_RETURN%", " -> void"); } else { _template = _template.replace("%INT_TYPE%", ""); @@ -466,7 +466,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na if (th) { String type = p_args[i].get_slice(":", 1); if (!type.empty() && type != "var") { - s += " : " + type; + s += ": " + type; } } } @@ -2596,7 +2596,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base } method_hint += arg; if (use_type_hint && mi.arguments[i].type != Variant::NIL) { - method_hint += " : "; + method_hint += ": "; if (mi.arguments[i].type == Variant::OBJECT && mi.arguments[i].class_name != StringName()) { method_hint += mi.arguments[i].class_name.operator String(); } else { diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index bae3f48923..d615b58b24 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -191,6 +191,7 @@ static String _get_var_type(const Variant *p_type) { static const void *switch_table_ops[] = { \ &&OPCODE_OPERATOR, \ &&OPCODE_EXTENDS_TEST, \ + &&OPCODE_IS_BUILTIN, \ &&OPCODE_SET, \ &&OPCODE_GET, \ &&OPCODE_SET_NAMED, \ @@ -536,6 +537,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_IS_BUILTIN) { + + CHECK_SPACE(4); + + GET_VARIANT_PTR(value, 1); + Variant::Type var_type = (Variant::Type)_code_ptr[ip + 2]; + GET_VARIANT_PTR(dst, 3); + + GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); + + *dst = value->get_type() == var_type; + ip += 4; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_SET) { CHECK_SPACE(3); diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 3ce84290fd..633cca35d3 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -136,6 +136,7 @@ public: enum Opcode { OPCODE_OPERATOR, OPCODE_EXTENDS_TEST, + OPCODE_IS_BUILTIN, OPCODE_SET, OPCODE_GET, OPCODE_SET_NAMED, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a3f5e1819e..7502f09d8a 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -861,6 +861,20 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s op->arguments.push_back(subexpr); expr=op;*/ + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_IS && tokenizer->get_token(1) == GDScriptTokenizer::TK_BUILT_IN_TYPE) { + // 'is' operator with built-in type + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_IS_BUILTIN; + op->arguments.push_back(expr); + + tokenizer->advance(); + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = tokenizer->get_token_type(); + op->arguments.push_back(tn); + tokenizer->advance(); + + expr = op; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_OPEN) { // array tokenizer->advance(); @@ -1071,6 +1085,15 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = op; + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && expression.size() > 0 && expression[expression.size() - 1].is_op && expression[expression.size() - 1].op == OperatorNode::OP_IS) { + Expression e = expression[expression.size() - 1]; + e.op = OperatorNode::OP_IS_BUILTIN; + expression.write[expression.size() - 1] = e; + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = tokenizer->get_token_type(); + expr = tn; + tokenizer->advance(); } else { //find list [ or find dictionary { @@ -1329,6 +1352,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s switch (expression[i].op) { case OperatorNode::OP_IS: + case OperatorNode::OP_IS_BUILTIN: priority = -1; break; //before anything @@ -3915,14 +3939,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") { - //current_export.hint=PROPERTY_HINT_ALL_FLAGS; tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + ERR_EXPLAIN("Exporting bit flags hint requires string constants."); + WARN_DEPRECATED break; } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { - _set_error("Expected ')' or ',' in bit flags hint."); + _set_error("Expected ',' in bit flags hint."); return; } @@ -5793,6 +5818,13 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case Node::TYPE_CONSTANT: { node_type = _type_from_variant(static_cast<ConstantNode *>(p_node)->value); } break; + case Node::TYPE_TYPE: { + TypeNode *tn = static_cast<TypeNode *>(p_node); + node_type.has_type = true; + node_type.is_meta_type = true; + node_type.kind = DataType::BUILTIN; + node_type.builtin_type = tn->vtype; + } break; case Node::TYPE_ARRAY: { node_type.has_type = true; node_type.kind = DataType::BUILTIN; @@ -5896,7 +5928,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { // yield can return anything node_type.has_type = false; } break; - case OperatorNode::OP_IS: { + case OperatorNode::OP_IS: + case OperatorNode::OP_IS_BUILTIN: { if (op->arguments.size() != 2) { _set_error("Parser bug: binary operation without 2 arguments.", op->line); @@ -5913,8 +5946,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } type_type.is_meta_type = false; // Test the actual type if (!_is_type_compatible(type_type, value_type) && !_is_type_compatible(value_type, type_type)) { - // TODO: Make this a warning? - _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line); + if (op->op == OperatorNode::OP_IS) { + _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line); + } else { + _set_error("A value of type '" + value_type.to_string() + "' will never be of type '" + type_type.to_string() + "'.", op->line); + } return DataType(); } } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index dbe523a0b9..3c51e3f372 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -345,6 +345,7 @@ public: OP_PARENT_CALL, OP_YIELD, OP_IS, + OP_IS_BUILTIN, //indexing operator OP_INDEX, OP_INDEX_NAMED, diff --git a/modules/mobile_vr/shaders/lens_distorted.glsl b/modules/mobile_vr/shaders/lens_distorted.glsl index 5a2975d737..92604c891c 100644 --- a/modules/mobile_vr/shaders/lens_distorted.glsl +++ b/modules/mobile_vr/shaders/lens_distorted.glsl @@ -1,7 +1,9 @@ +/* clang-format off */ [vertex] -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; uniform float offset_x; @@ -9,13 +11,15 @@ out vec2 uv_interp; void main() { - uv_interp = uv_in; - gl_Position = vec4(vertex_attrib.x + offset_x, vertex_attrib.y, 0.0, 1.0); + uv_interp = uv_in; + gl_Position = vec4(vertex_attrib.x + offset_x, vertex_attrib.y, 0.0, 1.0); } +/* clang-format off */ [fragment] uniform sampler2D source; //texunit:0 +/* clang-format on */ uniform vec2 eye_center; uniform float k1; @@ -28,32 +32,31 @@ in vec2 uv_interp; layout(location = 0) out vec4 frag_color; void main() { - vec2 coords = uv_interp; - vec2 offset = coords - eye_center; - - // take aspect ratio into account - offset.y /= aspect_ratio; - - // distort - vec2 offset_sq = offset * offset; - float radius_sq = offset_sq.x + offset_sq.y; - float radius_s4 = radius_sq * radius_sq; - float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4); - offset *= distortion_scale; - - // reapply aspect ratio - offset.y *= aspect_ratio; - - // add our eye center back in - coords = offset + eye_center; - coords /= upscale; - - // and check our color - if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { - frag_color = vec4(0.0, 0.0, 0.0, 1.0); - } else { - coords = (coords + vec2(1.0)) / vec2(2.0); - frag_color = textureLod(source, coords, 0.0); - } + vec2 coords = uv_interp; + vec2 offset = coords - eye_center; + + // take aspect ratio into account + offset.y /= aspect_ratio; + + // distort + vec2 offset_sq = offset * offset; + float radius_sq = offset_sq.x + offset_sq.y; + float radius_s4 = radius_sq * radius_sq; + float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4); + offset *= distortion_scale; + + // reapply aspect ratio + offset.y *= aspect_ratio; + + // add our eye center back in + coords = offset + eye_center; + coords /= upscale; + + // and check our color + if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { + frag_color = vec4(0.0, 0.0, 0.0, 1.0); + } else { + coords = (coords + vec2(1.0)) / vec2(2.0); + frag_color = textureLod(source, coords, 0.0); + } } - diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index b8b77924f7..d2a861dbe8 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1013,6 +1013,69 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { #endif } +void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { + + Reference *ref_owner = Object::cast_to<Reference>(p_object); + +#ifdef DEBUG_ENABLED + CRASH_COND(!ref_owner); +#endif + + void *data = p_object->get_script_instance_binding(get_language_index()); + if (!data) + return; + Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get(); + + if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 + // The reference count was increased after the managed side was the only one referencing our owner. + // This means the owner is being referenced again by the unmanaged side, + // so the owner must hold the managed side alive again to avoid it from being GCed. + + MonoObject *target = gchandle->get_target(); + if (!target) + return; // Called after the managed side was collected, so nothing to do here + + // Release the current weak handle and replace it with a strong handle. + uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(target); + gchandle->release(); + gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE); + } +} + +bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { + + Reference *ref_owner = Object::cast_to<Reference>(p_object); + +#ifdef DEBUG_ENABLED + CRASH_COND(!ref_owner); +#endif + + int refcount = ref_owner->reference_get_count(); + + void *data = p_object->get_script_instance_binding(get_language_index()); + if (!data) + return refcount == 0; + Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get(); + + if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 + // If owner owner is no longer referenced by the unmanaged side, + // the managed instance takes responsibility of deleting the owner when GCed. + + MonoObject *target = gchandle->get_target(); + if (!target) + return refcount == 0; // Called after the managed side was collected, so nothing to do here + + // Release the current strong handle and replace it with a weak handle. + uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(target); + gchandle->release(); + gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE); + + return false; + } + + return refcount == 0; +} + CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle) { CSharpInstance *instance = memnew(CSharpInstance); @@ -1303,11 +1366,13 @@ void CSharpInstance::mono_object_disposed() { void CSharpInstance::refcount_incremented() { +#ifdef DEBUG_ENABLED CRASH_COND(!base_ref); +#endif Reference *ref_owner = Object::cast_to<Reference>(owner); - if (ref_owner->reference_get_count() > 1) { // The managed side also holds a reference, hence 1 instead of 0 + if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 // The reference count was increased after the managed side was the only one referencing our owner. // This means the owner is being referenced again by the unmanaged side, // so the owner must hold the managed side alive again to avoid it from being GCed. @@ -1315,26 +1380,28 @@ void CSharpInstance::refcount_incremented() { // Release the current weak handle and replace it with a strong handle. uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(gchandle->get_target()); gchandle->release(); - gchandle->set_handle(strong_gchandle); + gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE); } } bool CSharpInstance::refcount_decremented() { +#ifdef DEBUG_ENABLED CRASH_COND(!base_ref); +#endif Reference *ref_owner = Object::cast_to<Reference>(owner); int refcount = ref_owner->reference_get_count(); - if (refcount == 1) { // The managed side also holds a reference, hence 1 instead of 0 + if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 // If owner owner is no longer referenced by the unmanaged side, // the managed instance takes responsibility of deleting the owner when GCed. // Release the current strong handle and replace it with a weak handle. uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(gchandle->get_target()); gchandle->release(); - gchandle->set_handle(weak_gchandle); + gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE); return false; } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 53644eafae..1a5d0c8a69 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -346,6 +346,8 @@ public: // Don't use these. I'm watching you virtual void *alloc_instance_binding_data(Object *p_object); virtual void free_instance_binding_data(void *p_data); + virtual void refcount_incremented_instance_binding(Object *p_object); + virtual bool refcount_decremented_instance_binding(Object *p_object); #ifdef DEBUG_ENABLED Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b97bb5e95f..cc954348f4 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -533,7 +533,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo cs_icalls_content.push_back("using System;\n" "using System.Runtime.CompilerServices;\n" - "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); @@ -638,7 +637,6 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, cs_icalls_content.push_back("using System;\n" "using System.Runtime.CompilerServices;\n" - "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK); @@ -711,10 +709,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str List<String> output; output.push_back("using System;\n"); // IntPtr - - if (itype.requires_collections) - output.push_back("using System.Collections.Generic;\n"); // Dictionary - + output.push_back("\n#pragma warning disable CS1591 // Disable warning: " + "'Missing XML comment for publicly visible type or member'\n"); output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); const DocData::ClassDoc *class_doc = itype.class_doc; @@ -737,8 +733,15 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(INDENT1 "public "); - bool is_abstract = itype.is_object_type && !ClassDB::can_instance(itype.name) && ClassDB::is_class_enabled(itype.name); // can_instance returns true if there's a constructor and the class is not 'disabled' - output.push_back(itype.is_singleton ? "static partial class " : (is_abstract ? "abstract partial class " : "partial class ")); + if (itype.is_object_type) { + if (itype.is_singleton) { + output.push_back("static partial class "); + } else { + output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class "); + } + } else { + output.push_back("partial class "); + } output.push_back(itype.proxy_name); if (itype.is_singleton) { @@ -1034,7 +1037,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str custom_icalls.push_back(ctor_icall); } - output.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); + output.push_back(INDENT1 CLOSE_BLOCK /* class */ + CLOSE_BLOCK /* namespace */); + + output.push_back("\n#pragma warning restore CS1591\n"); return _save_file(p_output_file, output); } @@ -1922,9 +1928,6 @@ void BindingsGenerator::_populate_object_type_interfaces() { imethod.return_type.cname = Variant::get_type_name(return_info.type); } - if (!itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary) - itype.requires_collections = true; - for (int i = 0; i < argc; i++) { PropertyInfo arginfo = method_info.arguments[i]; @@ -1946,9 +1949,6 @@ void BindingsGenerator::_populate_object_type_interfaces() { iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name)); - if (!itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary) - itype.requires_collections = true; - if (m && m->has_default_argument(i)) { _default_argument_from_variant(m->get_default_argument(i), iarg); } @@ -2371,14 +2371,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface(); itype.name = "Array"; itype.cname = itype.name; - itype.proxy_name = "Array"; + itype.proxy_name = itype.name; itype.c_out = "\treturn memnew(Array(%1));\n"; itype.c_type = itype.name; itype.c_type_in = itype.c_type + "*"; itype.c_type_out = itype.c_type + "*"; - itype.cs_type = itype.proxy_name; + itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()"; - itype.cs_out = "return new Array(%0);"; + itype.cs_out = "return new " + itype.cs_type + "(%0);"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; builtin_types.insert(itype.cname, itype); @@ -2387,14 +2387,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface(); itype.name = "Dictionary"; itype.cname = itype.name; - itype.proxy_name = "Dictionary"; + itype.proxy_name = itype.name; itype.c_out = "\treturn memnew(Dictionary(%1));\n"; itype.c_type = itype.name; itype.c_type_in = itype.c_type + "*"; itype.c_type_out = itype.c_type + "*"; - itype.cs_type = itype.proxy_name; + itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()"; - itype.cs_out = "return new Dictionary(%0);"; + itype.cs_out = "return new " + itype.cs_type + "(%0);"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; builtin_types.insert(itype.cname, itype); @@ -2441,9 +2441,6 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: else iarg.type.cname = Variant::get_type_name(pi.type); - if (!r_itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary) - r_itype.requires_collections = true; - if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0) _default_argument_from_variant(Variant::construct(pi.type, NULL, 0, cerror), iarg); @@ -2457,9 +2454,6 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: imethod.return_type.cname = Variant::get_type_name(mi.return_val.type); } - if (!r_itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary) - r_itype.requires_collections = true; - if (r_itype.class_doc) { for (int i = 0; i < r_itype.class_doc->methods.size(); i++) { if (r_itype.class_doc->methods[i].name == imethod.name) { diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 5b33a0e53f..735e7ce7cc 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -192,7 +192,7 @@ class BindingsGenerator { /** * Used only by Object-derived types. - * Determines if this type is not virtual (incomplete). + * Determines if this type is not abstract (incomplete). * e.g.: CanvasItem cannot be instantiated. */ bool is_instantiable; @@ -204,12 +204,6 @@ class BindingsGenerator { */ bool memory_own; - /** - * Determines if the file must have a using directive for System.Collections.Generic - * e.g.: When the generated class makes use of Dictionary - */ - bool requires_collections; - // !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name] // !! When renaming those fields, make sure to rename their references in the comments @@ -295,7 +289,7 @@ class BindingsGenerator { /** * Type used for method signatures, both for parameters and the return type. - * Same as [proxy_name] except for variable arguments (VarArg). + * Same as [proxy_name] except for variable arguments (VarArg) and collections (which include the namespace). */ String cs_type; @@ -414,7 +408,6 @@ class BindingsGenerator { is_instantiable = false; memory_own = false; - requires_collections = false; c_arg_in = "%s"; diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index 148bb32398..bb218b49b7 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -209,32 +209,32 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb } void godot_register_collections_icalls() { - mono_add_internal_call("Godot.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor); - mono_add_internal_call("Godot.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor); - mono_add_internal_call("Godot.Array::godot_icall_Array_At", (void *)godot_icall_Array_At); - mono_add_internal_call("Godot.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt); - mono_add_internal_call("Godot.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count); - mono_add_internal_call("Godot.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add); - mono_add_internal_call("Godot.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear); - mono_add_internal_call("Godot.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains); - mono_add_internal_call("Godot.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo); - mono_add_internal_call("Godot.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf); - mono_add_internal_call("Godot.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert); - mono_add_internal_call("Godot.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove); - mono_add_internal_call("Godot.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt); - - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Count", (void *)godot_icall_Dictionary_Count); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Add", (void *)godot_icall_Dictionary_Add); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove); - mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At", (void *)godot_icall_Array_At); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt); + + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", (void *)godot_icall_Dictionary_Count); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", (void *)godot_icall_Dictionary_Add); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue); } diff --git a/modules/mono/glue/cs_files/Array.cs b/modules/mono/glue/cs_files/Array.cs index 1ec4d7d20a..2f0185b1e3 100644 --- a/modules/mono/glue/cs_files/Array.cs +++ b/modules/mono/glue/cs_files/Array.cs @@ -4,7 +4,7 @@ using System.Collections; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace Godot +namespace Godot.Collections { class ArraySafeHandle : SafeHandle { diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index c280d32c61..10286f3832 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -426,7 +426,7 @@ namespace Godot public Basis(Quat quat) { - real_t s = 2.0f / quat.LengthSquared(); + real_t s = 2.0f / quat.LengthSquared; real_t xs = quat.x * s; real_t ys = quat.y * s; diff --git a/modules/mono/glue/cs_files/Dictionary.cs b/modules/mono/glue/cs_files/Dictionary.cs index 30d17c2a59..64cb9f935d 100644 --- a/modules/mono/glue/cs_files/Dictionary.cs +++ b/modules/mono/glue/cs_files/Dictionary.cs @@ -4,7 +4,7 @@ using System.Collections; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace Godot +namespace Godot.Collections { class DictionarySafeHandle : SafeHandle { diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/cs_files/MarshalUtils.cs index 6ad4b3dcb2..f7699a15bf 100644 --- a/modules/mono/glue/cs_files/MarshalUtils.cs +++ b/modules/mono/glue/cs_files/MarshalUtils.cs @@ -1,4 +1,5 @@ using System; +using Godot.Collections; namespace Godot { diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs index c69c55d997..eaa027eb69 100644 --- a/modules/mono/glue/cs_files/Quat.cs +++ b/modules/mono/glue/cs_files/Quat.cs @@ -11,18 +11,11 @@ namespace Godot [StructLayout(LayoutKind.Sequential)] public struct Quat : IEquatable<Quat> { - private static readonly Quat identity = new Quat(0f, 0f, 0f, 1f); - public real_t x; public real_t y; public real_t z; public real_t w; - public static Quat Identity - { - get { return identity; } - } - public real_t this[int index] { get @@ -63,6 +56,16 @@ namespace Godot } } + public real_t Length + { + get { return Mathf.Sqrt(LengthSquared); } + } + + public real_t LengthSquared + { + get { return Dot(this); } + } + public Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t t) { real_t t2 = (1.0f - t) * t * 2f; @@ -76,24 +79,20 @@ namespace Godot return x * b.x + y * b.y + z * b.z + w * b.w; } - public Quat Inverse() - { - return new Quat(-x, -y, -z, w); - } - - public real_t Length() + public Vector3 GetEuler() { - return Mathf.Sqrt(LengthSquared()); + var basis = new Basis(this); + return basis.GetEuler(); } - public real_t LengthSquared() + public Quat Inverse() { - return Dot(this); + return new Quat(-x, -y, -z, w); } public Quat Normalized() { - return this / Length(); + return this / Length; } public void Set(real_t x, real_t y, real_t z, real_t w) @@ -103,12 +102,20 @@ namespace Godot this.z = z; this.w = w; } + public void Set(Quat q) { - x = q.x; - y = q.y; - z = q.z; - w = q.w; + this = q; + } + + public void SetAxisAngle(Vector3 axis, real_t angle) + { + this = new Quat(axis, angle); + } + + public void SetEuler(Vector3 eulerYXZ) + { + this = new Quat(eulerYXZ); } public Quat Slerp(Quat b, real_t t) @@ -192,6 +199,9 @@ namespace Godot return new Vector3(q.x, q.y, q.z); } + // Static Readonly Properties + public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f); + // Constructors public Quat(real_t x, real_t y, real_t z, real_t w) { @@ -199,15 +209,46 @@ namespace Godot this.y = y; this.z = z; this.w = w; - } + } + + public bool IsNormalized() + { + return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon; + } + public Quat(Quat q) - { - x = q.x; - y = q.y; - z = q.z; - w = q.w; + { + this = q; + } + + public Quat(Basis basis) + { + this = basis.Quat(); } - + + public Quat(Vector3 eulerYXZ) + { + real_t half_a1 = eulerYXZ.y * (real_t)0.5; + real_t half_a2 = eulerYXZ.x * (real_t)0.5; + real_t half_a3 = eulerYXZ.z * (real_t)0.5; + + // R = Y(a1).X(a2).Z(a3) convention for Euler angles. + // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6) + // a3 is the angle of the first rotation, following the notation in this reference. + + real_t cos_a1 = Mathf.Cos(half_a1); + real_t sin_a1 = Mathf.Sin(half_a1); + real_t cos_a2 = Mathf.Cos(half_a2); + real_t sin_a2 = Mathf.Sin(half_a2); + real_t cos_a3 = Mathf.Cos(half_a3); + real_t sin_a3 = Mathf.Sin(half_a3); + + x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3; + y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3; + z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3; + w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3; + } + public Quat(Vector3 axis, real_t angle) { real_t d = axis.Length(); diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index f604464e8f..39d608de9f 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -32,6 +32,7 @@ #define GODOTSHARP_DEFS_H #define BINDINGS_NAMESPACE "Godot" +#define BINDINGS_NAMESPACE_COLLECTIONS BINDINGS_NAMESPACE ".Collections" #define BINDINGS_GLOBAL_SCOPE_CLASS "GD" #define BINDINGS_PTR_FIELD "ptr" #define BINDINGS_NATIVE_NAME_FIELD "nativeName" diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp index 12109045e0..9f0e933a8c 100644 --- a/modules/mono/mono_gc_handle.cpp +++ b/modules/mono/mono_gc_handle.cpp @@ -44,12 +44,12 @@ uint32_t MonoGCHandle::make_weak_handle(MonoObject *p_object) { Ref<MonoGCHandle> MonoGCHandle::create_strong(MonoObject *p_object) { - return memnew(MonoGCHandle(make_strong_handle(p_object))); + return memnew(MonoGCHandle(make_strong_handle(p_object), STRONG_HANDLE)); } Ref<MonoGCHandle> MonoGCHandle::create_weak(MonoObject *p_object) { - return memnew(MonoGCHandle(make_weak_handle(p_object))); + return memnew(MonoGCHandle(make_weak_handle(p_object), WEAK_HANDLE)); } void MonoGCHandle::release() { @@ -64,9 +64,10 @@ void MonoGCHandle::release() { } } -MonoGCHandle::MonoGCHandle(uint32_t p_handle) { +MonoGCHandle::MonoGCHandle(uint32_t p_handle, HandleType p_handle_type) { released = false; + weak = p_handle_type == WEAK_HANDLE; handle = p_handle; } diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index 9cb3ef0fbb..7eeaba30e0 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -40,24 +40,33 @@ class MonoGCHandle : public Reference { GDCLASS(MonoGCHandle, Reference) bool released; + bool weak; uint32_t handle; public: + enum HandleType { + STRONG_HANDLE, + WEAK_HANDLE + }; + static uint32_t make_strong_handle(MonoObject *p_object); static uint32_t make_weak_handle(MonoObject *p_object); static Ref<MonoGCHandle> create_strong(MonoObject *p_object); static Ref<MonoGCHandle> create_weak(MonoObject *p_object); + _FORCE_INLINE_ bool is_weak() { return weak; } + _FORCE_INLINE_ MonoObject *get_target() const { return released ? NULL : mono_gchandle_get_target(handle); } - _FORCE_INLINE_ void set_handle(uint32_t p_handle) { - handle = p_handle; + _FORCE_INLINE_ void set_handle(uint32_t p_handle, HandleType p_handle_type) { released = false; + weak = p_handle_type == WEAK_HANDLE; + handle = p_handle; } void release(); - MonoGCHandle(uint32_t p_handle); + MonoGCHandle(uint32_t p_handle, HandleType p_handle_type); ~MonoGCHandle(); }; diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index bebc3b863f..c1f56bc3d2 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -156,6 +156,7 @@ void MonoCache::cleanup() { } #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) +#define GODOT_API_NS_CLAS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class)) void update_corlib_cache() { @@ -206,8 +207,8 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); - CACHE_CLASS_AND_CHECK(Array, GODOT_API_CLASS(Array)); - CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_CLASS(Dictionary)); + CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)); + CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)); CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); #ifdef DEBUG_ENABLED @@ -234,8 +235,8 @@ void update_godot_api_cache() { CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD)); CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD)); - CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_CLASS(Array)->get_method_thunk("GetPtr", 0)); - CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_CLASS(Dictionary)->get_method_thunk("GetPtr", 0)); + CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method_thunk("GetPtr", 0)); + CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method_thunk("GetPtr", 0)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsArrayGenericType", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsDictionaryGenericType, (IsDictionaryGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsDictionaryGenericType", 1)); CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("SignalCallback", 1)); diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 54720652fa..add1e506ea 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -42,8 +42,7 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p ERR_FAIL_NULL_V(p_source, ERR_INVALID_DATA); ERR_FAIL_NULL_V(p_target, ERR_INVALID_DATA); - uint32_t awaiter_handle = MonoGCHandle::make_strong_handle(p_awaiter); - Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(awaiter_handle)); + Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(p_awaiter)); #ifdef DEBUG_ENABLED sa_con->set_connection_target(p_target); #endif @@ -119,8 +118,8 @@ void SignalAwaiterHandle::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &SignalAwaiterHandle::_signal_callback, MethodInfo("_signal_callback")); } -SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_managed_handle) : - MonoGCHandle(p_managed_handle) { +SignalAwaiterHandle::SignalAwaiterHandle(MonoObject *p_managed) : + MonoGCHandle(MonoGCHandle::make_strong_handle(p_managed), STRONG_HANDLE) { #ifdef DEBUG_ENABLED conn_target_id = 0; diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h index a6a205ff8d..1920432709 100644 --- a/modules/mono/signal_awaiter_utils.h +++ b/modules/mono/signal_awaiter_utils.h @@ -64,7 +64,7 @@ public: } #endif - SignalAwaiterHandle(uint32_t p_managed_handle); + SignalAwaiterHandle(MonoObject *p_managed); ~SignalAwaiterHandle(); }; diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index 733f32277b..bdd3e31eb8 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -205,6 +205,8 @@ Error RegEx::compile(const String &p_pattern) { code = pcre2_compile_16(p, pattern.length(), flags, &err, &offset, cctx); + pcre2_compile_context_free_16(cctx); + if (!code) { PCRE2_UCHAR16 buf[256]; pcre2_get_error_message_16(err, buf, 256); @@ -221,6 +223,8 @@ Error RegEx::compile(const String &p_pattern) { code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx); + pcre2_compile_context_free_32(cctx); + if (!code) { PCRE2_UCHAR32 buf[256]; pcre2_get_error_message_32(err, buf, 256); @@ -285,6 +289,8 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) if (res < 0) { pcre2_match_data_free_32(match); + pcre2_match_context_free_32(mctx); + return NULL; } diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index 653dd82351..bb8a4bdbea 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -193,8 +193,8 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres int src_ofs = p_image->get_mipmap_offset(i); squish::CompressImage(&rb[src_ofs], w, h, &wb[dst_ofs], squish_comp); dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift; - w >>= 1; - h >>= 1; + w = MAX(w / 2, 1); + h = MAX(h / 2, 1); } rb = PoolVector<uint8_t>::Read(); diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 0abefe11ee..b19bcfefcb 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -129,15 +129,45 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f PoolVector<uint8_t> imgdata; Image::Format format; + int output_channels = 0; if (idxA > 0) { imgdata.resize(exr_image.width * exr_image.height * 8); //RGBA16 format = Image::FORMAT_RGBAH; + output_channels = 4; } else { imgdata.resize(exr_image.width * exr_image.height * 6); //RGB16 format = Image::FORMAT_RGBH; + output_channels = 3; + } + + EXRTile single_image_tile; + int num_tiles; + int tile_width = 0; + int tile_height = 0; + + const EXRTile *exr_tiles; + + if (!exr_header.tiled) { + single_image_tile.images = exr_image.images; + single_image_tile.width = exr_image.width; + single_image_tile.height = exr_image.height; + single_image_tile.level_x = exr_image.width; + single_image_tile.level_y = exr_image.height; + single_image_tile.offset_x = 0; + single_image_tile.offset_y = 0; + + exr_tiles = &single_image_tile; + num_tiles = 1; + tile_width = exr_image.width; + tile_height = exr_image.height; + } else { + tile_width = exr_header.tile_size_x; + tile_height = exr_header.tile_size_y; + num_tiles = exr_image.num_tiles; + exr_tiles = exr_image.tiles; } { @@ -145,22 +175,51 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f uint16_t *iw = (uint16_t *)wd.ptr(); // Assume `out_rgba` have enough memory allocated. - for (int i = 0; i < exr_image.width * exr_image.height; i++) { + for (int tile_index = 0; tile_index < num_tiles; tile_index++) { - Color color( - reinterpret_cast<float **>(exr_image.images)[idxR][i], - reinterpret_cast<float **>(exr_image.images)[idxG][i], - reinterpret_cast<float **>(exr_image.images)[idxB][i]); + const EXRTile &tile = exr_tiles[tile_index]; - if (p_force_linear) - color = color.to_linear(); + int tw = tile.width; + int th = tile.height; - *iw++ = Math::make_half_float(color.r); - *iw++ = Math::make_half_float(color.g); - *iw++ = Math::make_half_float(color.b); + const float *r_channel_start = reinterpret_cast<const float *>(tile.images[idxR]); + const float *g_channel_start = reinterpret_cast<const float *>(tile.images[idxG]); + const float *b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]); + const float *a_channel_start = NULL; if (idxA > 0) { - *iw++ = Math::make_half_float(reinterpret_cast<float **>(exr_image.images)[idxA][i]); + a_channel_start = reinterpret_cast<const float *>(tile.images[idxA]); + } + + uint16_t *first_row_w = iw + (tile.offset_y * tile_height * exr_image.width + tile.offset_x * tile_width) * output_channels; + + for (int y = 0; y < th; y++) { + const float *r_channel = r_channel_start + y * tile_width; + const float *g_channel = g_channel_start + y * tile_width; + const float *b_channel = b_channel_start + y * tile_width; + const float *a_channel = NULL; + + if (a_channel_start) { + a_channel = a_channel_start + y * tile_width; + } + + uint16_t *row_w = first_row_w + (y * exr_image.width * output_channels); + + for (int x = 0; x < tw; x++) { + + Color color(*r_channel++, *g_channel++, *b_channel++); + + if (p_force_linear) + color = color.to_linear(); + + *row_w++ = Math::make_half_float(color.r); + *row_w++ = Math::make_half_float(color.g); + *row_w++ = Math::make_half_float(color.b); + + if (idxA > 0) { + *row_w++ = Math::make_half_float(*a_channel++); + } + } } } } |