bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name) { String assembly_file = p_assembly_name + ".dll"; String assembly_src = p_src_dir.plus_file(assembly_file); String assembly_dst = p_dst_dir.plus_file(assembly_file); if (!FileAccess::exists(assembly_dst) || FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst)) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String xml_file = p_assembly_name + ".xml"; if (da->copy(p_src_dir.plus_file(xml_file), p_dst_dir.plus_file(xml_file)) != OK) WARN_PRINTS("Failed to copy " + xml_file); String pdb_file = p_assembly_name + ".pdb"; if (da->copy(p_src_dir.plus_file(pdb_file), p_dst_dir.plus_file(pdb_file)) != OK) WARN_PRINTS("Failed to copy " + pdb_file); Error err = da->copy(assembly_src, assembly_dst); memdelete(da); if (err != OK) { show_build_error_dialog("Failed to copy " API_ASSEMBLY_NAME ".dll"); return false; } } return true; }
void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer::HINGE_JOINT_BIAS: if (0 < p_value) { print_line("The Bullet Hinge Joint doesn't support bias, 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; case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: hingeConstraint->setLimit(p_value, hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), p_value, hingeConstraint->getLimitRelaxationFactor()); break; case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), p_value, hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), p_value); break; case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: hingeConstraint->setMotorTargetVelocity(p_value); break; case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: hingeConstraint->setMaxMotorImpulse(p_value); break; default: WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param) + ", value: " + itos(p_value)); } }
void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { switch (p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: btBody->setRestitution(p_value); break; case PhysicsServer::BODY_PARAM_FRICTION: btBody->setFriction(p_value); break; case PhysicsServer::BODY_PARAM_MASS: { ERR_FAIL_COND(p_value < 0); mass = p_value; _internal_set_mass(p_value); break; } case PhysicsServer::BODY_PARAM_LINEAR_DAMP: linearDamp = p_value; btBody->setDamping(linearDamp, angularDamp); break; case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: angularDamp = p_value; btBody->setDamping(linearDamp, angularDamp); break; case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: gravity_scale = p_value; /// The Bullet gravity will be is set by reload_space_override_modificator scratch_space_override_modificator(); break; default: WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet. Value: " + itos(p_value)); } }
void EditorAddonLibrary::_image_request_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data,int p_queue_id) { ERR_FAIL_COND( !image_queue.has(p_queue_id) ); if (p_status==HTTPRequest::RESULT_SUCCESS) { print_line("GOT IMAGE YAY!"); Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target); if (obj) { int len=p_data.size(); ByteArray::Read r=p_data.read(); Image image(r.ptr(),len); if (!image.empty()) { Ref<ImageTexture> tex; tex.instance(); tex->create_from_image(image); obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,tex); } } } else { WARN_PRINTS("Error getting PNG file for asset id "+itos(image_queue[p_queue_id].asset_id)); } image_queue[p_queue_id].request->queue_delete();; image_queue.erase(p_queue_id); _update_image_queue(); }
void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { switch (p_param) { case PhysicsServer::AREA_PARAM_GRAVITY: set_spOv_gravityMag(p_value); break; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: set_spOv_gravityVec(p_value); break; case PhysicsServer::AREA_PARAM_LINEAR_DAMP: set_spOv_linearDump(p_value); break; case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: set_spOv_angularDump(p_value); break; case PhysicsServer::AREA_PARAM_PRIORITY: set_spOv_priority(p_value); break; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: set_spOv_gravityPoint(p_value); break; case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: set_spOv_gravityPointDistanceScale(p_value); break; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: set_spOv_gravityPointAttenuation(p_value); break; default: WARN_PRINTS("Area doesn't support this parameter in the Bullet backend: " + itos(p_param)); } }
void StreamPeerMbedTLS::_load_certs(const PoolByteArray &p_array) { int arr_len = p_array.size(); PoolByteArray::Read r = p_array.read(); int err = mbedtls_x509_crt_parse(&cacert, &r[0], arr_len); if (err != 0) { WARN_PRINTS("Error parsing some certificates: " + itos(err)); } }
int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { Ref<LWSPeer> peer = static_cast<Ref<LWSPeer> >(_peer); LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user; switch (reason) { case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: { PoolByteArray arr = StreamPeerSSL::get_project_cert_array(); if (arr.size() > 0) SSL_CTX_add_client_CA((SSL_CTX *)user, d2i_X509(NULL, &arr.read()[0], arr.size())); else if (verify_ssl) WARN_PRINTS("No CA cert specified in project settings, SSL will not work"); } break; case LWS_CALLBACK_CLIENT_ESTABLISHED: peer->set_wsi(wsi); peer_data->peer_id = 0; peer_data->force_close = false; _on_connect(lws_get_protocol(wsi)->name); break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: _on_error(); destroy_context(); return -1; // we should close the connection (would probably happen anyway) case LWS_CALLBACK_CLIENT_CLOSED: peer->close(); destroy_context(); _on_disconnect(); return 0; // we can end here case LWS_CALLBACK_CLIENT_RECEIVE: peer->read_wsi(in, len); if (peer->get_available_packet_count() > 0) _on_peer_packet(); break; case LWS_CALLBACK_CLIENT_WRITEABLE: if (peer_data->force_close) return -1; peer->write_wsi(); break; default: break; } return 0; }
void AudioEffectRecord::set_recording_active(bool p_record) { if (p_record) { if (current_instance == 0) { WARN_PRINTS("Recording should not be set as active before Godot has initialized."); recording_active = false; return; } ensure_thread_stopped(); current_instance->init(); } recording_active = p_record; }
Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const { switch (p_state) { case PhysicsServer::BODY_STATE_TRANSFORM: return get_transform(); case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: return get_linear_velocity(); case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: return get_angular_velocity(); case PhysicsServer::BODY_STATE_SLEEPING: return !is_active(); case PhysicsServer::BODY_STATE_CAN_SLEEP: return can_sleep; default: WARN_PRINTS("This state " + itos(p_state) + " is not supported by Bullet"); return Variant(); } }
real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { switch (p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: return btBody->getRestitution(); case PhysicsServer::BODY_PARAM_FRICTION: return btBody->getFriction(); case PhysicsServer::BODY_PARAM_MASS: { const btScalar invMass = btBody->getInvMass(); return 0 == invMass ? 0 : 1 / invMass; } case PhysicsServer::BODY_PARAM_LINEAR_DAMP: return linearDamp; case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: return angularDamp; case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: return gravity_scale; default: WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet"); return 0; } }
Error AudioDriverWASAPI::init_render_device(bool reinit) { Error err = audio_device_init(&audio_output, false, reinit); if (err != OK) return err; switch (audio_output.channels) { case 2: // Stereo case 4: // Surround 3.1 case 6: // Surround 5.1 case 8: // Surround 7.1 channels = audio_output.channels; break; default: WARN_PRINTS("WASAPI: Unsupported number of channels: " + itos(audio_output.channels)); channels = 2; break; } UINT32 max_frames; HRESULT hr = audio_output.audio_client->GetBufferSize(&max_frames); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Due to WASAPI Shared Mode we have no control of the buffer size buffer_frames = max_frames; // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) samples_in.resize(buffer_frames * channels); input_position = 0; input_size = 0; print_verbose("WASAPI: detected " + itos(channels) + " channels"); print_verbose("WASAPI: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); return OK; }
Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const { switch (p_param) { case PhysicsServer::AREA_PARAM_GRAVITY: return spOv_gravityMag; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: return spOv_gravityVec; case PhysicsServer::AREA_PARAM_LINEAR_DAMP: return spOv_linearDump; case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: return spOv_angularDump; case PhysicsServer::AREA_PARAM_PRIORITY: return spOv_priority; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return spOv_gravityPoint; case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return spOv_gravityPointDistanceScale; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return spOv_gravityPointAttenuation; default: WARN_PRINTS("Area doesn't support this parameter in the Bullet backend: " + itos(p_param)); return Variant(); } }
real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const { switch (p_param) { case PhysicsServer::HINGE_JOINT_BIAS: return 0; break; case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: return hingeConstraint->getUpperLimit(); case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: return hingeConstraint->getLowerLimit(); case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: return hingeConstraint->getLimitBiasFactor(); case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: return hingeConstraint->getLimitSoftness(); case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: return hingeConstraint->getLimitRelaxationFactor(); case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return hingeConstraint->getMotorTargetVelocity(); case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: return hingeConstraint->getMaxMotorImpulse(); default: WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param)); return 0; } }
void EditorPluginSettings::update_plugins() { plugin_list->clear(); DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); Error err = da->change_dir("res://addons"); if (err!=OK) { memdelete(da); return; } updating=true; TreeItem *root = plugin_list->create_item(); da->list_dir_begin(); String d = da->get_next(); Vector<String> plugins; while(d!=String()) { bool dir = da->current_is_dir(); String path = "res://addons/"+d+"/plugin.cfg"; if (dir && FileAccess::exists(path)) { plugins.push_back(d); } d = da->get_next(); } da->list_dir_end(); memdelete(da); plugins.sort(); Vector<String> active_plugins = GlobalConfig::get_singleton()->get("plugins/active"); for(int i=0;i<plugins.size();i++) { Ref<ConfigFile> cf; cf.instance(); String path = "res://addons/"+plugins[i]+"/plugin.cfg"; Error err = cf->load(path); if (err!=OK) { WARN_PRINTS("Can't load plugin config: "+path); } else if (!cf->has_section_key("plugin","name")) { WARN_PRINTS("Plugin misses plugin/name: "+path); } else if (!cf->has_section_key("plugin","author")) { WARN_PRINTS("Plugin misses plugin/author: "+path); } else if (!cf->has_section_key("plugin","version")) { WARN_PRINTS("Plugin misses plugin/version: "+path); } else if (!cf->has_section_key("plugin","description")) { WARN_PRINTS("Plugin misses plugin/description: "+path); } else if (!cf->has_section_key("plugin","script")) { WARN_PRINTS("Plugin misses plugin/script: "+path); } else { String d = plugins[i]; String name = cf->get_value("plugin","name"); String author = cf->get_value("plugin","author"); String version = cf->get_value("plugin","version"); String description = cf->get_value("plugin","description"); String script = cf->get_value("plugin","script"); TreeItem *item = plugin_list->create_item(root); item->set_text(0,name); item->set_tooltip(0,"Name: "+name+"\nPath: "+path+"\nMain Script: "+script); item->set_metadata(0,d); item->set_text(1,version); item->set_metadata(1,script); item->set_text(2,author); item->set_metadata(2,description); item->set_cell_mode(3,TreeItem::CELL_MODE_RANGE); item->set_range_config(3,0,1,1); item->set_text(3,"Inactive,Active"); item->set_editable(3,true); if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) { item->set_custom_color(3,Color(0.2,1,0.2)); item->set_range(3,1); } else { item->set_custom_color(3,Color(1,0.2,0.2)); item->set_range(3,0); } } } updating=false; }
Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { path_src = p_path; path = fix_path(p_path); if (f) close(); const wchar_t *mode_string; if (p_mode_flags == READ) mode_string = L"rb"; else if (p_mode_flags == WRITE) mode_string = L"wb"; else if (p_mode_flags == READ_WRITE) mode_string = L"rb+"; else if (p_mode_flags == WRITE_READ) mode_string = L"wb+"; else return ERR_INVALID_PARAMETER; /* pretty much every implementation that uses fopen as primary backend supports utf8 encoding */ struct _stat st; if (_wstat(path.c_str(), &st) == 0) { if (!S_ISREG(st.st_mode)) return ERR_FILE_CANT_OPEN; }; #ifdef TOOLS_ENABLED // Windows is case insensitive, but all other platforms are sensitive to it // To ease cross-platform development, we issue a warning if users try to access // a file using the wrong case (which *works* on Windows, but won't on other // platforms). if (p_mode_flags == READ) { WIN32_FIND_DATAW d = { 0 }; HANDLE f = FindFirstFileW(path.c_str(), &d); if (f) { String fname = d.cFileName; if (fname != String()) { String base_file = path.get_file(); if (base_file != fname && base_file.findn(fname) == 0) { WARN_PRINTS("Case mismatch opening requested file '" + base_file + "', stored as '" + fname + "' in the filesystem. This file will not open when exported to other case-sensitive platforms."); } } FindClose(f); } } #endif if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) { save_path = path; path = path + ".tmp"; } _wfopen_s(&f, path.c_str(), mode_string); if (f == NULL) { last_error = ERR_FILE_CANT_OPEN; return ERR_FILE_CANT_OPEN; } else { last_error = OK; flags = p_mode_flags; return OK; } }
Error AudioDriverPulseAudio::init_device() { // If there is a specified device check that it is really present if (device_name != "Default") { Array list = get_device_list(); if (list.find(device_name) == -1) { device_name = "Default"; new_device = "Default"; } } // Detect the amount of channels PulseAudio is using // Note: If using an even amount of channels (2, 4, etc) channels and pa_map.channels will be equal, // if not then pa_map.channels will have the real amount of channels PulseAudio is using and channels // will have the amount of channels Godot is using (in this case it's pa_map.channels + 1) detect_channels(); switch (pa_map.channels) { case 1: // Mono case 3: // Surround 2.1 case 5: // Surround 5.0 case 7: // Surround 7.0 channels = pa_map.channels + 1; break; case 2: // Stereo case 4: // Surround 4.0 case 6: // Surround 5.1 case 8: // Surround 7.1 channels = pa_map.channels; break; default: WARN_PRINTS("PulseAudio: Unsupported number of channels: " + itos(pa_map.channels)); pa_channel_map_init_stereo(&pa_map); channels = 2; break; } int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); pa_buffer_size = buffer_frames * pa_map.channels; print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " channels"); print_verbose("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); pa_sample_spec spec; spec.format = PA_SAMPLE_S16LE; spec.channels = pa_map.channels; spec.rate = mix_rate; pa_str = pa_stream_new(pa_ctx, "Sound", &spec, &pa_map); if (pa_str == NULL) { ERR_PRINTS("PulseAudio: pa_stream_new error: " + String(pa_strerror(pa_context_errno(pa_ctx)))); ERR_FAIL_V(ERR_CANT_OPEN); } pa_buffer_attr attr; // set to appropriate buffer length (in bytes) from global settings // Note: PulseAudio defaults to 4 fragments, which means that the actual // latency is tlength / fragments. It seems that the PulseAudio has no way // to get the fragments number so we're hardcoding this to the default of 4 const int fragments = 4; attr.tlength = pa_buffer_size * sizeof(int16_t) * fragments; // set them to be automatically chosen attr.prebuf = (uint32_t)-1; attr.maxlength = (uint32_t)-1; attr.minreq = (uint32_t)-1; const char *dev = device_name == "Default" ? NULL : device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_playback(pa_str, dev, &attr, flags, NULL, NULL); ERR_FAIL_COND_V(error_code < 0, ERR_CANT_OPEN); samples_in.resize(buffer_frames * channels); samples_out.resize(pa_buffer_size); // Reset audio input to keep synchronisation. input_position = 0; input_size = 0; return OK; }
void EditorFileSystem::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_TREE: { scan(); } break; case NOTIFICATION_EXIT_TREE: { if (use_threads && thread) { //abort thread if in progress abort_scan=true; while(scanning) { OS::get_singleton()->delay_usec(1000); } Thread::wait_to_finish(thread); memdelete(thread); thread=NULL; WARN_PRINTS("Scan thread aborted..."); set_process(false); } if (filesystem) memdelete(filesystem); if (new_filesystem) memdelete(new_filesystem); filesystem=NULL; new_filesystem=NULL; } break; case NOTIFICATION_PROCESS: { if (use_threads) { if (scanning_sources) { if (scanning_sources_done) { scanning_sources=false; set_process(false); Thread::wait_to_finish(thread_sources); memdelete(thread_sources); thread_sources=NULL; if (_update_scan_actions()) emit_signal("filesystem_changed"); //print_line("sources changed: "+itos(sources_changed.size())); emit_signal("sources_changed",sources_changed.size()>0); } } else if (!scanning) { set_process(false); if (filesystem) memdelete(filesystem); filesystem=new_filesystem; new_filesystem=NULL; Thread::wait_to_finish(thread); memdelete(thread); thread=NULL; _update_scan_actions(); emit_signal("filesystem_changed"); emit_signal("sources_changed",sources_changed.size()>0); //print_line("initial sources changed: "+itos(sources_changed.size())); } else { //progress->set_text("Scanning...\n"+itos(total*100)+"%"); } } } break; } }
void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, MonoString **r_framework_path) { GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool"))); #if defined(WINDOWS_ENABLED) switch (build_tool) { case GodotSharpBuilds::MSBUILD: { static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); if (msbuild_tools_path.length()) { if (!msbuild_tools_path.ends_with("\\")) msbuild_tools_path += "\\"; // FrameworkPathOverride const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); if (mono_reg_info.assembly_dir.length()) { *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5"); *r_framework_path = GDMonoMarshal::mono_string_from_godot(framework_path); } else { ERR_PRINT("Cannot find Mono's assemblies directory in the registry"); } return; } if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n"); } // fall through case GodotSharpBuilds::MSBUILD_MONO: { String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat"); if (!FileAccess::exists(msbuild_path)) { WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path); } *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_path); return; } break; default: ERR_EXPLAIN("You don't deserve to live"); CRASH_NOW(); } #elif defined(UNIX_ENABLED) static String msbuild_path = _find_build_engine_on_unix("msbuild"); static String xbuild_path = _find_build_engine_on_unix("xbuild"); if (build_tool != GodotSharpBuilds::XBUILD) { if (msbuild_path.empty()) { WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool')."); return; } } else { if (xbuild_path.empty()) { WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool')."); return; } } *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path); return; #else ERR_PRINT("Not implemented on this platform"); return; #endif }
void EditorFileSystem::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { call_deferred("scan"); //this should happen after every editor node entered the tree } break; case NOTIFICATION_EXIT_TREE: { if (use_threads && thread) { //abort thread if in progress abort_scan = true; while (scanning) { OS::get_singleton()->delay_usec(1000); } Thread::wait_to_finish(thread); memdelete(thread); thread = NULL; WARN_PRINTS("Scan thread aborted..."); set_process(false); } if (filesystem) memdelete(filesystem); if (new_filesystem) memdelete(new_filesystem); filesystem = NULL; new_filesystem = NULL; } break; case NOTIFICATION_PROCESS: { if (use_threads) { if (scanning_changes) { if (scanning_changes_done) { scanning_changes = false; set_process(false); Thread::wait_to_finish(thread_sources); memdelete(thread_sources); thread_sources = NULL; if (_update_scan_actions()) emit_signal("filesystem_changed"); emit_signal("sources_changed", sources_changed.size() > 0); } } else if (!scanning) { set_process(false); if (filesystem) memdelete(filesystem); filesystem = new_filesystem; new_filesystem = NULL; Thread::wait_to_finish(thread); memdelete(thread); thread = NULL; _update_scan_actions(); emit_signal("filesystem_changed"); emit_signal("sources_changed", sources_changed.size() > 0); } } } break; } }
void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) { CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this)); if (methods_fetched) return; void *iter = NULL; MonoMethod *raw_method = NULL; while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { StringName name = mono_method_get_name(raw_method); // get_method implicitly fetches methods and adds them to this->methods GDMonoMethod *method = get_method(raw_method, name); ERR_CONTINUE(!method); if (method->get_name() != name) { #ifdef DEBUG_ENABLED String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")"; WARN_PRINTS("Method `" + fullname + "` is hidden by Godot API method. Should be `" + method->get_full_name_no_class() + "`. In class `" + namespace_name + "." + class_name + "`."); #endif continue; } #ifdef DEBUG_ENABLED // For debug builds, we also fetched from native base classes as well before if this is not a native base class. // This allows us to warn the user here if he is using snake_case by mistake. if (p_native_base != this) { GDMonoClass *native_top = p_native_base; while (native_top) { GDMonoMethod *m = native_top->get_method(name, method->get_parameters_count()); if (m && m->get_name() != name) { // found String fullname = m->get_ret_type_full_name() + " " + name + "(" + m->get_signature_desc(true) + ")"; WARN_PRINTS("Method `" + fullname + "` should be `" + m->get_full_name_no_class() + "`. In class `" + namespace_name + "." + class_name + "`."); break; } if (native_top == CACHED_CLASS(GodotObject)) break; native_top = native_top->get_parent_class(); } } #endif uint32_t flags = mono_method_get_flags(method->mono_method, NULL); if (!(flags & MONO_METHOD_ATTR_VIRTUAL)) continue; // Virtual method of Godot Object derived type, let's try to find GodotMethod attribute GDMonoClass *top = p_native_base; while (top) { GDMonoMethod *base_method = top->get_method(name, method->get_parameters_count()); if (base_method && base_method->has_attribute(CACHED_CLASS(GodotMethodAttribute))) { // Found base method with GodotMethod attribute. // We get the original API method name from this attribute. // This name must point to the virtual method. MonoObject *attr = base_method->get_attribute(CACHED_CLASS(GodotMethodAttribute)); StringName godot_method_name = CACHED_FIELD(GodotMethodAttribute, methodName)->get_string_value(attr); #ifdef DEBUG_ENABLED CRASH_COND(godot_method_name == StringName()); #endif MethodKey key = MethodKey(godot_method_name, method->get_parameters_count()); GDMonoMethod **existing_method = methods.getptr(key); if (existing_method) memdelete(*existing_method); // Must delete old one methods.set(key, method); break; } if (top == CACHED_CLASS(GodotObject)) break; top = top->get_parent_class(); } } methods_fetched = true; }
Error AudioDriverWASAPI::init_device(bool reinit) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = NULL; IMMDevice *device = NULL; CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device); if (reinit) { // In case we're trying to re-initialize the device prevent throwing this error on the console, // otherwise if there is currently no device available this will spam the console. if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = enumerator->RegisterEndpointNotificationCallback(¬if_client); if (hr != S_OK) { ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error"); } hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client); if (reinit) { if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = audio_client->GetMixFormat(&pwfex); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along wasapi_channels = pwfex->nChannels; mix_rate = pwfex->nSamplesPerSec; format_tag = pwfex->wFormatTag; bits_per_sample = pwfex->wBitsPerSample; switch (wasapi_channels) { case 2: // Stereo //case 6: // Surround 5.1 //case 8: // Surround 7.1 channels = wasapi_channels; break; default: WARN_PRINTS("WASAPI: Unsupported number of channels (" + itos(wasapi_channels) + ")"); channels = 2; } if (format_tag == WAVE_FORMAT_EXTENSIBLE) { WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex; if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) { format_tag = WAVE_FORMAT_PCM; } else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) { format_tag = WAVE_FORMAT_IEEE_FLOAT; } else { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } else { if (format_tag != WAVE_FORMAT_PCM && format_tag != WAVE_FORMAT_IEEE_FLOAT) { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, pwfex, NULL); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); event = CreateEvent(NULL, FALSE, FALSE, NULL); ERR_FAIL_COND_V(event == NULL, ERR_CANT_OPEN); hr = audio_client->SetEventHandle(event); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); hr = audio_client->GetService(IID_IAudioRenderClient, (void **)&render_client); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); UINT32 max_frames; hr = audio_client->GetBufferSize(&max_frames); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Due to WASAPI Shared Mode we have no control of the buffer size buffer_frames = max_frames; // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_size = buffer_frames * channels; samples_in.resize(buffer_size); if (OS::get_singleton()->is_stdout_verbose()) { print_line("audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); } return OK; }