feat(web): add audio speaker and particle authoring
This commit is contained in:
@@ -1585,7 +1585,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
type == "moveObjectToCollection" || type == "renameId" || type == "joinObjects" ||
|
||||
type == "separateMeshFaces" || type == "applyObjectTransform" || type == "setObjectOrigin" ||
|
||||
type == "setCurveControlPoints" || type == "setCurveHandle" || type == "setCurveTopology" || type == "setCurveSplines" || type == "setSurfaceTopology" || type == "setFontBody" ||
|
||||
type == "setFontProperties" || type == "setFontAdvanced" || type == "importVFont" || type == "setFontLinks" || type == "setTextSource" || type == "setVolumeProperties" || type == "deleteNonMeshData" ||
|
||||
type == "setFontProperties" || type == "setFontAdvanced" || type == "importVFont" || type == "setFontLinks" || type == "setTextSource" || type == "setSoundProperties" || type == "setSpeakerProperties" || type == "setParticleSettings" || type == "setVolumeProperties" || type == "deleteNonMeshData" ||
|
||||
type == "setMetaballElements" || type == "createGreasePencilLayer" ||
|
||||
type == "removeGreasePencilLayer" || type == "moveGreasePencilLayer" ||
|
||||
type == "moveGreasePencilFrame" ||
|
||||
@@ -1999,6 +1999,51 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(),
|
||||
command.value("source", "").c_str(), main_error);
|
||||
}
|
||||
else if (type == "setSoundProperties") {
|
||||
const json properties = command.value("properties", json::object());
|
||||
WebSoundPropertiesEdit edit;
|
||||
edit.volume = properties.value("volume", -1.0f);
|
||||
edit.attenuation = properties.value("attenuation", -1.0f);
|
||||
edit.pitch = properties.value("pitch", -1.0f);
|
||||
edit.min_gain = properties.value("minGain", -1.0f);
|
||||
edit.max_gain = properties.value("maxGain", -1.0f);
|
||||
edit.distance = properties.value("distance", -1.0f);
|
||||
edit.offset_time = properties.value("offsetTime", -1.0);
|
||||
applied = web_engine_blend_main_set_sound_properties(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(), edit, main_error);
|
||||
}
|
||||
else if (type == "setSpeakerProperties") {
|
||||
const json properties = command.value("properties", json::object());
|
||||
WebSpeakerPropertiesEdit edit;
|
||||
edit.volume_max = properties.value("volumeMax", -1.0f);
|
||||
edit.volume_min = properties.value("volumeMin", -1.0f);
|
||||
edit.distance_max = properties.value("distanceMax", -1.0f);
|
||||
edit.distance_reference = properties.value("distanceReference", -1.0f);
|
||||
edit.attenuation = properties.value("attenuation", -1.0f);
|
||||
edit.cone_angle_outer = properties.value("coneAngleOuter", -1.0f);
|
||||
edit.cone_angle_inner = properties.value("coneAngleInner", -1.0f);
|
||||
edit.cone_volume_outer = properties.value("coneVolumeOuter", -1.0f);
|
||||
edit.volume = properties.value("volume", -1.0f);
|
||||
edit.pitch = properties.value("pitch", -1.0f);
|
||||
applied = web_engine_blend_main_set_speaker_properties(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(), edit, main_error);
|
||||
}
|
||||
else if (type == "setParticleSettings") {
|
||||
const json properties = command.value("properties", json::object());
|
||||
WebParticleSettingsEdit edit;
|
||||
edit.type = properties.value("type", -1);
|
||||
edit.from = properties.value("from", -1);
|
||||
edit.distribution = properties.value("distribution", -1);
|
||||
edit.physics_type = properties.value("physicsType", -1);
|
||||
edit.total_particles = properties.value("totalParticles", -1);
|
||||
edit.start = properties.value("start", -1.0f);
|
||||
edit.end = properties.value("end", -1.0f);
|
||||
edit.lifetime = properties.value("lifetime", -1.0f);
|
||||
edit.size = properties.value("size", -1.0f);
|
||||
edit.draw_size = properties.value("drawSize", -1.0f);
|
||||
applied = web_engine_blend_main_set_particle_settings(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(), edit, main_error);
|
||||
}
|
||||
else if (type == "setVolumeProperties") {
|
||||
WebVolumePropertiesEdit properties;
|
||||
properties.source_path = command.value("sourcePath", "");
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_sound_types.h"
|
||||
#include "DNA_speaker_types.h"
|
||||
#include "DNA_text_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_userdef_enums.h"
|
||||
@@ -298,6 +300,30 @@ Volume *find_volume(Main *main, const char *data_id)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bSound *find_sound(Main *main, const char *data_id)
|
||||
{
|
||||
if (main == nullptr || data_id == nullptr || strncmp(data_id, "sound:", 6) != 0) return nullptr;
|
||||
const std::string name(data_id + 6);
|
||||
for (bSound &sound : main->sounds) if (id_name(sound.id) == name) return &sound;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Speaker *find_speaker(Main *main, const char *data_id)
|
||||
{
|
||||
if (main == nullptr || data_id == nullptr || strncmp(data_id, "speaker:", 8) != 0) return nullptr;
|
||||
const std::string name(data_id + 8);
|
||||
for (Speaker &speaker : main->speakers) if (id_name(speaker.id) == name) return &speaker;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParticleSettings *find_particle_settings(Main *main, const char *data_id)
|
||||
{
|
||||
if (main == nullptr || data_id == nullptr || strncmp(data_id, "particle-settings:", 18) != 0) return nullptr;
|
||||
const std::string name(data_id + 18);
|
||||
for (ParticleSettings &settings : main->particles) if (id_name(settings.id) == name) return &settings;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Light *find_light(Main *main, const char *data_id)
|
||||
{
|
||||
if (main == nullptr || data_id == nullptr || strncmp(data_id, "light:", 6) != 0) return nullptr;
|
||||
@@ -4004,6 +4030,114 @@ bool web_engine_blend_main_set_text_source(WebBlendMainState *state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_sound_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebSoundPropertiesEdit &properties,
|
||||
std::string &error)
|
||||
{
|
||||
bSound *sound = find_sound(state != nullptr ? state->main : nullptr, data_id);
|
||||
if (sound == nullptr || sound->id.lib != nullptr) {
|
||||
error = "NON_MESH_DATA_UNSUPPORTED: Sound data-block was not found or is linked read-only";
|
||||
return false;
|
||||
}
|
||||
const auto valid = [](const float value, const float maximum) {
|
||||
return value < 0.0f || !std::isfinite(value) || value > maximum;
|
||||
};
|
||||
if ((properties.volume >= 0.0f && valid(properties.volume, 1000000.0f)) ||
|
||||
(properties.attenuation >= 0.0f && valid(properties.attenuation, 1000000.0f)) ||
|
||||
(properties.pitch >= 0.0f && valid(properties.pitch, 1000000.0f)) ||
|
||||
(properties.min_gain >= 0.0f && valid(properties.min_gain, 1000000.0f)) ||
|
||||
(properties.max_gain >= 0.0f && valid(properties.max_gain, 1000000.0f)) ||
|
||||
(properties.distance >= 0.0f && valid(properties.distance, 1000000.0f)) ||
|
||||
(properties.offset_time >= 0.0 && (!std::isfinite(properties.offset_time) || properties.offset_time > 1000000.0))) {
|
||||
error = "NON_MESH_PROPERTY_INVALID: Sound properties are outside the bounded range";
|
||||
return false;
|
||||
}
|
||||
if (properties.volume >= 0.0f) sound->volume = properties.volume;
|
||||
if (properties.attenuation >= 0.0f) sound->attenuation = properties.attenuation;
|
||||
if (properties.pitch >= 0.0f) sound->pitch = properties.pitch;
|
||||
if (properties.min_gain >= 0.0f) sound->min_gain = properties.min_gain;
|
||||
if (properties.max_gain >= 0.0f) sound->max_gain = properties.max_gain;
|
||||
if (properties.distance >= 0.0f) sound->distance = properties.distance;
|
||||
if (properties.offset_time >= 0.0) sound->offset_time = properties.offset_time;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_speaker_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebSpeakerPropertiesEdit &properties,
|
||||
std::string &error)
|
||||
{
|
||||
Speaker *speaker = find_speaker(state != nullptr ? state->main : nullptr, data_id);
|
||||
if (speaker == nullptr || speaker->id.lib != nullptr) {
|
||||
error = "NON_MESH_DATA_UNSUPPORTED: Speaker data-block was not found or is linked read-only";
|
||||
return false;
|
||||
}
|
||||
const auto valid = [](const float value, const float maximum) {
|
||||
return value < 0.0f || !std::isfinite(value) || value > maximum;
|
||||
};
|
||||
if ((properties.volume_max >= 0.0f && valid(properties.volume_max, 1000000.0f)) ||
|
||||
(properties.volume_min >= 0.0f && valid(properties.volume_min, 1000000.0f)) ||
|
||||
(properties.distance_max >= 0.0f && valid(properties.distance_max, 1000000000.0f)) ||
|
||||
(properties.distance_reference >= 0.0f && valid(properties.distance_reference, 1000000000.0f)) ||
|
||||
(properties.attenuation >= 0.0f && valid(properties.attenuation, 1000000000.0f)) ||
|
||||
(properties.cone_angle_outer >= 0.0f && valid(properties.cone_angle_outer, 360.0f)) ||
|
||||
(properties.cone_angle_inner >= 0.0f && valid(properties.cone_angle_inner, 360.0f)) ||
|
||||
(properties.cone_volume_outer >= 0.0f && valid(properties.cone_volume_outer, 1.0f)) ||
|
||||
(properties.volume >= 0.0f && valid(properties.volume, 1000000.0f)) ||
|
||||
(properties.pitch >= 0.0f && valid(properties.pitch, 1000000.0f))) {
|
||||
error = "NON_MESH_PROPERTY_INVALID: Speaker properties are outside the bounded range";
|
||||
return false;
|
||||
}
|
||||
if (properties.volume_max >= 0.0f) speaker->volume_max = properties.volume_max;
|
||||
if (properties.volume_min >= 0.0f) speaker->volume_min = properties.volume_min;
|
||||
if (properties.distance_max >= 0.0f) speaker->distance_max = properties.distance_max;
|
||||
if (properties.distance_reference >= 0.0f) speaker->distance_reference = properties.distance_reference;
|
||||
if (properties.attenuation >= 0.0f) speaker->attenuation = properties.attenuation;
|
||||
if (properties.cone_angle_outer >= 0.0f) speaker->cone_angle_outer = properties.cone_angle_outer;
|
||||
if (properties.cone_angle_inner >= 0.0f) speaker->cone_angle_inner = properties.cone_angle_inner;
|
||||
if (properties.cone_volume_outer >= 0.0f) speaker->cone_volume_outer = properties.cone_volume_outer;
|
||||
if (properties.volume >= 0.0f) speaker->volume = properties.volume;
|
||||
if (properties.pitch >= 0.0f) speaker->pitch = properties.pitch;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_particle_settings(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebParticleSettingsEdit &properties,
|
||||
std::string &error)
|
||||
{
|
||||
ParticleSettings *settings = find_particle_settings(state != nullptr ? state->main : nullptr, data_id);
|
||||
if (settings == nullptr || settings->id.lib != nullptr) {
|
||||
error = "NON_MESH_DATA_UNSUPPORTED: ParticleSettings data-block was not found or is linked read-only";
|
||||
return false;
|
||||
}
|
||||
if ((properties.type >= 0 && properties.type > 2) || (properties.from >= 0 && properties.from > 4) ||
|
||||
(properties.distribution >= 0 && properties.distribution > 2) || (properties.physics_type >= 0 && properties.physics_type > 4) ||
|
||||
(properties.total_particles >= 0 && properties.total_particles > 1000000)) {
|
||||
error = "NON_MESH_PROPERTY_INVALID: Particle enum or count is outside the bounded range";
|
||||
return false;
|
||||
}
|
||||
const auto valid = [](const float value) { return value < 0.0f || !std::isfinite(value) || value > 1000000.0f; };
|
||||
if ((properties.start >= 0.0f && valid(properties.start)) || (properties.end >= 0.0f && valid(properties.end)) ||
|
||||
(properties.lifetime >= 0.0f && valid(properties.lifetime)) || (properties.size >= 0.0f && valid(properties.size)) ||
|
||||
(properties.draw_size >= 0.0f && valid(properties.draw_size))) {
|
||||
error = "NON_MESH_PROPERTY_INVALID: Particle numeric settings are outside the bounded range";
|
||||
return false;
|
||||
}
|
||||
if (properties.type >= 0) settings->type = eParticleType(properties.type);
|
||||
if (properties.from >= 0) settings->from = eParticleFrom(properties.from);
|
||||
if (properties.distribution >= 0) settings->distr = eParticleDistribution(properties.distribution);
|
||||
if (properties.physics_type >= 0) settings->phystype = eParticlePhysicsType(properties.physics_type);
|
||||
if (properties.total_particles >= 0) settings->totpart = properties.total_particles;
|
||||
if (properties.start >= 0.0f) settings->sta = properties.start;
|
||||
if (properties.end >= 0.0f) settings->end = properties.end;
|
||||
if (properties.lifetime >= 0.0f) settings->lifetime = properties.lifetime;
|
||||
if (properties.size >= 0.0f) settings->size = properties.size;
|
||||
if (properties.draw_size >= 0.0f) settings->draw_size = properties.draw_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_volume_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebVolumePropertiesEdit &properties,
|
||||
|
||||
@@ -76,6 +76,42 @@ struct WebVolumePropertiesEdit {
|
||||
float velocity_scale = 1.0f;
|
||||
};
|
||||
|
||||
struct WebSoundPropertiesEdit {
|
||||
float volume = -1.0f;
|
||||
float attenuation = -1.0f;
|
||||
float pitch = -1.0f;
|
||||
float min_gain = -1.0f;
|
||||
float max_gain = -1.0f;
|
||||
float distance = -1.0f;
|
||||
double offset_time = -1.0;
|
||||
};
|
||||
|
||||
struct WebSpeakerPropertiesEdit {
|
||||
float volume_max = -1.0f;
|
||||
float volume_min = -1.0f;
|
||||
float distance_max = -1.0f;
|
||||
float distance_reference = -1.0f;
|
||||
float attenuation = -1.0f;
|
||||
float cone_angle_outer = -1.0f;
|
||||
float cone_angle_inner = -1.0f;
|
||||
float cone_volume_outer = -1.0f;
|
||||
float volume = -1.0f;
|
||||
float pitch = -1.0f;
|
||||
};
|
||||
|
||||
struct WebParticleSettingsEdit {
|
||||
int type = -1;
|
||||
int from = -1;
|
||||
int distribution = -1;
|
||||
int physics_type = -1;
|
||||
int total_particles = -1;
|
||||
float start = -1.0f;
|
||||
float end = -1.0f;
|
||||
float lifetime = -1.0f;
|
||||
float size = -1.0f;
|
||||
float draw_size = -1.0f;
|
||||
};
|
||||
|
||||
struct WebGreasePencilPointEdit {
|
||||
std::array<float, 3> position = {0.0f, 0.0f, 0.0f};
|
||||
float radius = 0.01f;
|
||||
@@ -370,6 +406,18 @@ bool web_engine_blend_main_set_text_source(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const char *source,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_sound_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebSoundPropertiesEdit &properties,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_speaker_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebSpeakerPropertiesEdit &properties,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_particle_settings(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebParticleSettingsEdit &properties,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_volume_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebVolumePropertiesEdit &properties,
|
||||
|
||||
Reference in New Issue
Block a user