diff options
-rw-r--r-- | core/bind/core_bind.cpp | 12 | ||||
-rw-r--r-- | core/bind/core_bind.h | 2 | ||||
-rw-r--r-- | doc/classes/@GDScript.xml | 52 | ||||
-rw-r--r-- | doc/classes/Geometry.xml | 39 | ||||
-rw-r--r-- | editor/editor_help.cpp | 75 | ||||
-rw-r--r-- | editor/plugins/abstract_polygon_2d_editor.cpp | 129 | ||||
-rw-r--r-- | editor/plugins/abstract_polygon_2d_editor.h | 5 | ||||
-rw-r--r-- | editor/plugins/line_2d_editor_plugin.cpp | 253 | ||||
-rw-r--r-- | editor/plugins/line_2d_editor_plugin.h | 68 | ||||
-rw-r--r-- | platform/javascript/SCsub | 3 | ||||
-rw-r--r-- | platform/javascript/audio_driver_javascript.cpp | 44 | ||||
-rw-r--r-- | platform/javascript/audio_driver_javascript.h | 5 | ||||
-rw-r--r-- | platform/javascript/audio_server_javascript.cpp | 853 | ||||
-rw-r--r-- | platform/javascript/audio_server_javascript.h | 229 | ||||
-rw-r--r-- | platform/javascript/os_javascript.h | 1 |
15 files changed, 299 insertions, 1471 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 12b892d873..c369f4bffe 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1316,6 +1316,16 @@ Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) { return Geometry::triangulate_polygon(p_polygon); } +Vector<Point2> _Geometry::convex_hull_2d(const Vector<Point2> &p_points) { + + return Geometry::convex_hull_2d(p_points); +} + +Vector<Vector3> _Geometry::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) { + + return Geometry::clip_polygon(p_points, p_plane); +} + Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) { Dictionary ret; @@ -1376,6 +1386,8 @@ void _Geometry::_bind_methods() { ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry::point_is_inside_triangle); ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry::triangulate_polygon); + ClassDB::bind_method(D_METHOD("convex_hull_2d", "points"), &_Geometry::convex_hull_2d); + ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry::clip_polygon); ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry::make_atlas); } diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 7f8c734e36..bbbb40d926 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -363,6 +363,8 @@ public: int get_uv84_normal_bit(const Vector3 &p_vector); Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon); + Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points); + Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane); Dictionary make_atlas(const Vector<Size2> &p_rects); diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index b61cf93ef7..9c1d9a1aa2 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -1050,6 +1050,58 @@ A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it. </description> </method> + <method name="wrapf"> + <return type="float"> + </return> + <argument index="0" name="value" type="float"> + </argument> + <argument index="1" name="min" type="float"> + </argument> + <argument index="2" name="max" type="float"> + </argument> + <description> + Wraps float [code]value[/code] between [code]min[/code] and [code]max[/code]. + Usable for creating loop-alike behavior or infinite surfaces. + [codeblock] + # a is 0.5 + a = wrapf(10.5, 0.0, 10.0) + [/codeblock] + [codeblock] + # a is 9.5 + a = wrapf(-0.5, 0.0, 10.0) + [/codeblock] + [codeblock] + # infinite loop between 0.0 and 0.99 + f = wrapf(f + 0.1, 0.0, 1.0) + [/codeblock] + </description> + </method> + <method name="wrapi"> + <return type="int"> + </return> + <argument index="0" name="value" type="int"> + </argument> + <argument index="1" name="min" type="int"> + </argument> + <argument index="2" name="max" type="int"> + </argument> + <description> + Wraps integer [code]value[/code] between [code]min[/code] and [code]max[/code]. + Usable for creating loop-alike behavior or infinite surfaces. + [codeblock] + # a is 0 + a = wrapi(10, 0, 10) + [/codeblock] + [codeblock] + # a is 9 + a = wrapi(-1, 0, 10) + [/codeblock] + [codeblock] + # infinite loop between 0 and 9 + frame = wrapi(frame + 1, 0, 10) + [/codeblock] + </description> + </method> <method name="yield"> <return type="GDFunctionState"> </return> diff --git a/doc/classes/Geometry.xml b/doc/classes/Geometry.xml index 49f32bc68f..1589a9a906 100644 --- a/doc/classes/Geometry.xml +++ b/doc/classes/Geometry.xml @@ -15,6 +15,7 @@ <argument index="0" name="extents" type="Vector3"> </argument> <description> + Returns an array with 6 [Plane]s that describe the sides of a box centered at the origin. The box size is defined by [code]extents[/code], which represents one (positive) corner of the box (i.e. half its actual size). </description> </method> <method name="build_capsule_planes"> @@ -31,6 +32,7 @@ <argument index="4" name="axis" type="int" enum="Vector3.Axis" default="2"> </argument> <description> + Returns an array of [Plane]s closely bounding a faceted capsule centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the side part of the capsule, whereas [code]lats[/code] gives the number of latitudinal steps at the bottom and top of the capsule. The parameter [code]axis[/code] describes the axis along which the capsule is oriented (0 for X, 1 for Y, 2 for Z). </description> </method> <method name="build_cylinder_planes"> @@ -45,6 +47,7 @@ <argument index="3" name="axis" type="int" enum="Vector3.Axis" default="2"> </argument> <description> + Returns an array of [Plane]s closely bounding a faceted cylinder centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the round part of the cylinder. The parameter [code]axis[/code] describes the axis along which the cylinder is oriented (0 for X, 1 for Y, 2 for Z). </description> </method> <method name="get_closest_point_to_segment"> @@ -57,6 +60,7 @@ <argument index="2" name="s2" type="Vector3"> </argument> <description> + Returns the 3d point on the 3d segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment. </description> </method> <method name="get_closest_point_to_segment_2d"> @@ -69,6 +73,7 @@ <argument index="2" name="s2" type="Vector2"> </argument> <description> + Returns the 2d point on the 2d segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment. </description> </method> <method name="get_closest_point_to_segment_uncapped"> @@ -81,6 +86,7 @@ <argument index="2" name="s2" type="Vector3"> </argument> <description> + Returns the 3d point on the 3d line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment. </description> </method> <method name="get_closest_point_to_segment_uncapped_2d"> @@ -93,6 +99,7 @@ <argument index="2" name="s2" type="Vector2"> </argument> <description> + Returns the 2d point on the 2d line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment. </description> </method> <method name="get_closest_points_between_segments"> @@ -107,6 +114,7 @@ <argument index="3" name="q2" type="Vector3"> </argument> <description> + Given the two 3d segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PoolVector3Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]). </description> </method> <method name="get_closest_points_between_segments_2d"> @@ -121,6 +129,7 @@ <argument index="3" name="q2" type="Vector2"> </argument> <description> + Given the two 2d segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PoolVector2Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]). </description> </method> <method name="get_uv84_normal_bit"> @@ -137,6 +146,7 @@ <argument index="0" name="sizes" type="PoolVector2Array"> </argument> <description> + Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is a vector of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2]. </description> </method> <method name="point_is_inside_triangle" qualifiers="const"> @@ -151,6 +161,7 @@ <argument index="3" name="c" type="Vector2"> </argument> <description> + Returns if [code]point[/code] is inside the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. </description> </method> <method name="ray_intersects_triangle"> @@ -167,6 +178,7 @@ <argument index="4" name="c" type="Vector3"> </argument> <description> + Tests if the 3d ray starting at [code]from[/code] with the direction of [code]dir[/code] intersects the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned. </description> </method> <method name="segment_intersects_circle"> @@ -181,6 +193,7 @@ <argument index="3" name="circle_radius" type="float"> </argument> <description> + Given the 2d segment ([code]segment_from[/code], [code]segment_to[/code]), returns the position on the segment (as a number between 0 and 1) at which the segment hits the circle that is located at position [code]circle_position[/code] and has radius [code]circle_radius[/code]. If the segment does not intersect the circle, -1 is returned (this is also the case if the line extending the segment would intersect the circle, but the segment does not). </description> </method> <method name="segment_intersects_convex"> @@ -193,6 +206,7 @@ <argument index="2" name="planes" type="Array"> </argument> <description> + Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PoolVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty. </description> </method> <method name="segment_intersects_cylinder"> @@ -207,6 +221,7 @@ <argument index="3" name="radius" type="float"> </argument> <description> + Checks if the segment ([code]from[/code], [code]to[/code]) intersects the cylinder with height [code]height[/code] that is centered at the origin and has radius [code]radius[/code]. If no, returns an empty [PoolVector3Array]. If an intersection takes place, the returned array contains the point of intersection and the cylinder's normal at the point of intersection. </description> </method> <method name="segment_intersects_segment_2d"> @@ -221,6 +236,7 @@ <argument index="3" name="to_b" type="Vector2"> </argument> <description> + Checks if the two segments ([code]from_a[/code], [code]to_a[/code]) and ([code]from_b[/code], [code]to_b[/code]) intersect. If yes, return the point of intersection as [Vector2]. If no intersection takes place, returns an empty [Variant]. </description> </method> <method name="segment_intersects_sphere"> @@ -235,6 +251,7 @@ <argument index="3" name="sphere_radius" type="float"> </argument> <description> + Checks if the segment ([code]from[/code], [code]to[/code]) intersects the sphere that is located at [code]sphere_position[/code] and has radius [code]sphere_radius[/code]. If no, returns an empty [PoolVector3Array]. If yes, returns a [PoolVector3Array] containing the point of intersection and the sphere's normal at the point of intersection. </description> </method> <method name="segment_intersects_triangle"> @@ -251,6 +268,7 @@ <argument index="4" name="c" type="Vector3"> </argument> <description> + Tests if the segment ([code]from[/code], [code]to[/code]) intersects the triangle [code]a[/code], [code]b[/code], [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned. </description> </method> <method name="triangulate_polygon"> @@ -259,6 +277,27 @@ <argument index="0" name="polygon" type="PoolVector2Array"> </argument> <description> + Triangulates the polygon specified by the points in [code]polygon[/code]. Returns a [PoolIntArray] where each triangle consists of three consecutive point indices into [code]polygon[/code] (i.e. the returned array will have [code]n * 3[/code] elements, with [code]n[/code] being the number of found triangles). If the triangulation did not succeed, an empty [PoolIntArray] is returned. + </description> + </method> + <method name="convex_hull_2d"> + <return type="PoolVector2Array"> + </return> + <argument index="0" name="points" type="PoolVector2Array"> + </argument> + <description> + Given an array of [Vector2]s, returns the convex hull as a list of points in counter-clockwise order. The last point is the same as the first one. + </description> + </method> + <method name="clip_polygon"> + <return type="PoolVector3Array"> + </return> + <argument index="0" name="points" type="PoolVector3Array"> + </argument> + <argument index="1" name="plane" type="Plane"> + </argument> + <description> + Clips the polygon defined by the points in [code]points[/code] against the [code]plane[/code] and returns the points of the clipped polygon. </description> </method> </methods> diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 2c4d3035a4..03cd2c9b6b 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1045,12 +1045,17 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->pop(); // end monofont if (cd.signals[i].description != "") { + class_desc->push_font(doc_font); class_desc->push_color(comment_color); - class_desc->add_text(" "); + class_desc->push_indent(1); + // class_desc->add_text(" "); _add_text(cd.signals[i].description); + class_desc->pop(); // indent class_desc->pop(); + class_desc->pop(); // font } class_desc->add_newline(); + class_desc->add_newline(); } class_desc->pop(); @@ -1129,11 +1134,14 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->pop(); if (enum_list[i].description != "") { class_desc->push_font(doc_font); - class_desc->add_text(" "); + //class_desc->add_text(" "); + class_desc->push_indent(1); class_desc->push_color(comment_color); _add_text(enum_list[i].description); class_desc->pop(); class_desc->pop(); + class_desc->pop(); // indent + class_desc->add_newline(); } class_desc->add_newline(); @@ -1177,11 +1185,14 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->pop(); if (constants[i].description != "") { class_desc->push_font(doc_font); - class_desc->add_text(" "); + class_desc->push_indent(1); + //class_desc->add_text(" "); class_desc->push_color(comment_color); _add_text(constants[i].description); class_desc->pop(); class_desc->pop(); + class_desc->pop(); // indent + class_desc->add_newline(); } class_desc->add_newline(); @@ -1231,54 +1242,62 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { method_line[cd.properties[i].name] = class_desc->get_line_count() - 2; + class_desc->push_table(2); + class_desc->set_table_column_expand(1, 1); + + class_desc->push_cell(); class_desc->push_font(doc_code_font); _add_type(cd.properties[i].type, cd.properties[i].enumeration); - class_desc->add_text(" "); + class_desc->pop(); // font + class_desc->pop(); // cell + + class_desc->push_cell(); + class_desc->push_font(doc_code_font); class_desc->push_color(headline_color); _add_text(cd.properties[i].name); - class_desc->pop(); //color - - class_desc->add_text(" "); + class_desc->pop(); // color + class_desc->pop(); // font + class_desc->pop(); // cell - class_desc->pop(); //font + //class_desc->add_text(" "); if (cd.properties[i].setter != "") { - class_desc->push_font(doc_font); - - class_desc->push_indent(2); - class_desc->push_color(comment_color); - class_desc->add_text("Setter: "); - class_desc->pop(); + class_desc->push_cell(); + class_desc->pop(); // cell + class_desc->push_cell(); + class_desc->push_font(doc_code_font); class_desc->push_color(text_color); class_desc->add_text(cd.properties[i].setter + "(value)"); - class_desc->pop(); //color - - class_desc->pop(); //indent - - class_desc->pop(); //font + class_desc->pop(); // color + class_desc->push_color(comment_color); + class_desc->add_text(" setter"); + class_desc->pop(); // color + class_desc->pop(); // font + class_desc->pop(); // cell } if (cd.properties[i].getter != "") { - class_desc->push_font(doc_font); - - class_desc->push_indent(2); - class_desc->push_color(comment_color); - class_desc->add_text("Getter: "); - class_desc->pop(); + class_desc->push_cell(); + class_desc->pop(); // cell + class_desc->push_cell(); + class_desc->push_font(doc_code_font); class_desc->push_color(text_color); class_desc->add_text(cd.properties[i].getter + "()"); class_desc->pop(); //color - - class_desc->pop(); //indent - + class_desc->push_color(comment_color); + class_desc->add_text(" getter"); + class_desc->pop(); //color class_desc->pop(); //font + class_desc->pop(); //cell } + class_desc->pop(); // table + class_desc->add_newline(); class_desc->push_color(text_color); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 2f839b96cf..f2f913d2b3 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -92,6 +92,11 @@ bool AbstractPolygon2DEditor::_is_empty() const { return true; } +bool AbstractPolygon2DEditor::_is_line() const { + + return false; +} + int AbstractPolygon2DEditor::_get_polygon_count() const { return 1; @@ -158,12 +163,23 @@ void AbstractPolygon2DEditor::_menu_option(int p_option) { mode = MODE_CREATE; button_create->set_pressed(true); button_edit->set_pressed(false); + button_delete->set_pressed(false); } break; case MODE_EDIT: { + wip_active = false; mode = MODE_EDIT; button_create->set_pressed(false); button_edit->set_pressed(true); + button_delete->set_pressed(false); + } break; + case MODE_DELETE: { + + wip_active = false; + mode = MODE_DELETE; + button_create->set_pressed(false); + button_edit->set_pressed(false); + button_delete->set_pressed(true); } break; } } @@ -174,8 +190,9 @@ void AbstractPolygon2DEditor::_notification(int p_what) { case NOTIFICATION_READY: { - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); + button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); + button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); + button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); button_edit->set_pressed(true); get_tree()->connect("node_removed", this, "_node_removed"); @@ -199,19 +216,32 @@ void AbstractPolygon2DEditor::_node_removed(Node *p_node) { } } +void AbstractPolygon2DEditor::_wip_changed() { + + if (wip_active && _is_line()) { + _set_polygon(0, wip); + } +} + void AbstractPolygon2DEditor::_wip_close() { + if (_is_line()) { - if (wip.size() >= 3) { + _set_polygon(0, wip); + } else if (wip.size() >= 3) { undo_redo->create_action(TTR("Create Poly")); _action_add_polygon(wip); _commit_action(); + } else { - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); + return; } + mode = MODE_EDIT; + button_edit->set_pressed(true); + button_create->set_pressed(false); + button_delete->set_pressed(false); + wip.clear(); wip_active = false; @@ -252,6 +282,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) wip.clear(); wip.push_back(cpoint); wip_active = true; + _wip_changed(); edited_point = PosVertex(-1, 1, cpoint); canvas_item_editor->get_viewport_control()->update(); hover_point = Vertex(); @@ -262,20 +293,20 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { + if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { //wip closed _wip_close(); return true; } else { + //add wip point wip.push_back(cpoint); + _wip_changed(); edited_point = PosVertex(-1, wip.size(), cpoint); selected_point = Vertex(wip.size() - 1); canvas_item_editor->get_viewport_control()->update(); return true; - - //add wip point } } } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { @@ -362,6 +393,18 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } + } else if (mode == MODE_DELETE) { + + if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + + const PosVertex closest = closest_point(gpoint); + + if (closest.valid()) { + + remove_point(closest); + return true; + } + } } } @@ -414,25 +457,33 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed() && (k->get_scancode() == KEY_DELETE || k->get_scancode() == KEY_BACKSPACE)) { - if (wip_active && selected_point.polygon == -1) { + if (k.is_valid() && k->is_pressed()) { - if (wip.size() > selected_point.vertex) { + if (k->get_scancode() == KEY_DELETE || k->get_scancode() == KEY_BACKSPACE) { - wip.remove(selected_point.vertex); - selected_point = wip.size() - 1; - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } else { + if (wip_active && selected_point.polygon == -1) { - const Vertex active_point = get_active_point(); + if (wip.size() > selected_point.vertex) { - if (active_point.valid()) { + wip.remove(selected_point.vertex); + _wip_changed(); + selected_point = wip.size() - 1; + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } else { + + const Vertex active_point = get_active_point(); + + if (active_point.valid()) { - remove_point(active_point); - return true; + remove_point(active_point); + return true; + } } + } else if (wip_active && k->get_scancode() == KEY_ENTER) { + + _wip_close(); } } @@ -451,6 +502,7 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { const Vertex active_point = get_active_point(); const int n_polygons = _get_polygon_count(); + const bool is_closed = !_is_line(); for (int j = -1; j < n_polygons; j++) { @@ -476,7 +528,7 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color(); const int n = pre_move_edit.size(); - for (int i = 0; i < n; i++) { + for (int i = 0; i < n - is_closed ? 0 : 1; i++) { Vector2 p, p2; p = pre_move_edit[i] + offset; @@ -496,17 +548,22 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { const Vertex vertex(j, i); - Vector2 p, p2; - p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset); - if (j == edited_point.polygon && ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point.vertex))) - p2 = edited_point.pos; - else - p2 = points[(i + 1) % n_points] + offset; + const Vector2 p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset); + const Vector2 point = xform.xform(p); - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); + if (is_closed || i < n_points - 1) { + + Vector2 p2; + if (j == edited_point.polygon && + ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point.vertex))) + p2 = edited_point.pos; + else + p2 = points[(i + 1) % n_points] + offset; + + const Vector2 next_point = xform.xform(p2); + vpc->draw_line(point, next_point, col, 2); + } - vpc->draw_line(point, next_point, col, 2); Ref<Texture> handle = vertex == active_point ? selected_handle : default_handle; vpc->draw_texture(handle, point - handle->get_size() * 0.5); } @@ -674,7 +731,7 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi add_child(button_create); button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create a new polygon from scratch.")); + button_create->set_tooltip(TTR("Create a new polygon from scratch")); button_edit = memnew(ToolButton); add_child(button_edit); @@ -682,6 +739,12 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi button_edit->set_toggle_mode(true); button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.")); + button_delete = memnew(ToolButton); + add_child(button_delete); + button_delete->connect("pressed", this, "_menu_option", varray(MODE_DELETE)); + button_delete->set_toggle_mode(true); + button_delete->set_tooltip(TTR("Delete points")); + create_resource = memnew(ConfirmationDialog); add_child(create_resource); create_resource->get_ok()->set_text(TTR("Create")); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 8dd22958db..915fe0803e 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -46,6 +46,7 @@ class AbstractPolygon2DEditor : public HBoxContainer { ToolButton *button_create; ToolButton *button_edit; + ToolButton *button_delete; struct Vertex { Vertex(); @@ -89,6 +90,7 @@ protected: MODE_CREATE, MODE_EDIT, + MODE_DELETE, MODE_CONT, }; @@ -98,7 +100,9 @@ protected: UndoRedo *undo_redo; virtual void _menu_option(int p_option); + void _wip_changed(); void _wip_close(); + bool _delete_point(const Vector2 &p_gpoint); void _notification(int p_what); void _node_removed(Node *p_node); @@ -116,6 +120,7 @@ protected: virtual Node2D *_get_node() const = 0; virtual void _set_node(Node *p_polygon) = 0; + virtual bool _is_line() const; virtual int _get_polygon_count() const; virtual Vector2 _get_offset(int p_idx) const; virtual Variant _get_polygon(int p_idx) const; diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp index 0533aaa9c0..51fa488b43 100644 --- a/editor/plugins/line_2d_editor_plugin.cpp +++ b/editor/plugins/line_2d_editor_plugin.cpp @@ -29,259 +29,42 @@ /*************************************************************************/ #include "line_2d_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "editor/editor_settings.h" -#include "os/file_access.h" -#include "os/keyboard.h" +Node2D *Line2DEditor::_get_node() const { -//---------------------------------------------------------------------------- -// Line2DEditor -//---------------------------------------------------------------------------- - -void Line2DEditor::_node_removed(Node *p_node) { - if (p_node == node) { - node = NULL; - hide(); - } -} - -void Line2DEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_VISIBILITY_CHANGED: - // This widget is not a child but should have the same visibility state - base_hb->set_visible(is_visible()); - break; - } -} - -int Line2DEditor::get_point_index_at(const Transform2D &xform, Vector2 gpos) { - ERR_FAIL_COND_V(node == 0, -1); - - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - - for (int i = 0; i < node->get_point_count(); ++i) { - Point2 p = xform.xform(node->get_point_position(i)); - if (gpos.distance_to(p) < grab_threshold) { - return i; - } - } - - return -1; -} - -bool Line2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { - - if (!node) - return false; - - if (!node->is_visible()) - return false; - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - - Vector2 gpoint = mb->get_position(); - Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); - - if (mb->is_pressed() && _dragging == false) { - int i = get_point_index_at(canvas_item_editor->get_canvas_transform() * node->get_global_transform(), gpoint); - if (i != -1) { - if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) { - _dragging = true; - action_point = i; - moving_from = node->get_point_position(i); - moving_screen_from = gpoint; - } else if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) { - undo_redo->create_action(TTR("Remove Point from Line2D")); - undo_redo->add_do_method(node, "remove_point", i); - undo_redo->add_undo_method(node, "add_point", node->get_point_position(i), i); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - } - return true; - } - } - - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) { - - undo_redo->create_action(TTR("Add Point to Line2D")); - undo_redo->add_do_method(node, "add_point", cpoint); - undo_redo->add_undo_method(node, "remove_point", node->get_point_count()); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - - _dragging = true; - action_point = node->get_point_count() - 1; - moving_from = node->get_point_position(action_point); - moving_screen_from = gpoint; - - canvas_item_editor->get_viewport_control()->update(); - - return true; - } - - if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && _dragging) { - undo_redo->create_action(TTR("Move Point in Line2D")); - undo_redo->add_do_method(node, "set_point_position", action_point, cpoint); - undo_redo->add_undo_method(node, "set_point_position", action_point, moving_from); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - _dragging = false; - return true; - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (_dragging) { - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()))); - node->set_point_position(action_point, cpoint); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } - - return false; + return node; } -void Line2DEditor::forward_draw_over_canvas(Control *p_canvas) { - - if (!node) - return; - - if (!node->is_visible()) - return; +void Line2DEditor::_set_node(Node *p_line) { - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); - Size2 handle_size = handle->get_size(); - - int len = node->get_point_count(); - Control *vpc = canvas_item_editor->get_viewport_control(); - - for (int i = 0; i < len; ++i) { - Vector2 point = xform.xform(node->get_point_position(i)); - vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false); - } + node = Object::cast_to<Line2D>(p_line); } -void Line2DEditor::_node_visibility_changed() { - if (!node) - return; - canvas_item_editor->get_viewport_control()->update(); -} - -void Line2DEditor::edit(Node *p_line2d) { - - if (!canvas_item_editor) - canvas_item_editor = CanvasItemEditor::get_singleton(); +bool Line2DEditor::_is_line() const { - if (p_line2d) { - node = Object::cast_to<Line2D>(p_line2d); - if (!node->is_connected("visibility_changed", this, "_node_visibility_changed")) - node->connect("visibility_changed", this, "_node_visibility_changed"); - } else { - // node may have been deleted at this point - if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed")) - node->disconnect("visibility_changed", this, "_node_visibility_changed"); - node = NULL; - } + return true; } -void Line2DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Line2DEditor::_node_visibility_changed); - ClassDB::bind_method(D_METHOD("_mode_selected"), &Line2DEditor::_mode_selected); -} +Variant Line2DEditor::_get_polygon(int p_idx) const { -void Line2DEditor::_mode_selected(int p_mode) { - for (int i = 0; i < _MODE_COUNT; ++i) { - toolbar_buttons[i]->set_pressed(i == p_mode); - } - mode = Mode(p_mode); + return _get_node()->get("points"); } -Line2DEditor::Line2DEditor(EditorNode *p_editor) { - - canvas_item_editor = NULL; - editor = p_editor; - undo_redo = editor->get_undo_redo(); - - _dragging = false; - - base_hb = memnew(HBoxContainer); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(base_hb); - - sep = memnew(VSeparator); - base_hb->add_child(sep); - - { - ToolButton *b = memnew(ToolButton); - b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); - b->set_toggle_mode(true); - b->set_focus_mode(Control::FOCUS_NONE); - b->set_tooltip( - TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); - b->connect("pressed", this, "_mode_selected", varray(MODE_EDIT)); - toolbar_buttons[MODE_EDIT] = b; - base_hb->add_child(b); - } +void Line2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { - { - ToolButton *b = memnew(ToolButton); - b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); - b->set_toggle_mode(true); - b->set_focus_mode(Control::FOCUS_NONE); - b->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in line)")); - b->connect("pressed", this, "_mode_selected", varray(MODE_CREATE)); - toolbar_buttons[MODE_CREATE] = b; - base_hb->add_child(b); - } - - { - ToolButton *b = memnew(ToolButton); - b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); - b->set_toggle_mode(true); - b->set_focus_mode(Control::FOCUS_NONE); - b->set_tooltip(TTR("Delete Point")); - b->connect("pressed", this, "_mode_selected", varray(MODE_DELETE)); - toolbar_buttons[MODE_DELETE] = b; - base_hb->add_child(b); - } - - base_hb->hide(); - hide(); - - _mode_selected(MODE_CREATE); + _get_node()->set("points", p_polygon); } -//---------------------------------------------------------------------------- -// Line2DEditorPlugin -//---------------------------------------------------------------------------- - -void Line2DEditorPlugin::edit(Object *p_object) { - line2d_editor->edit(Object::cast_to<Node>(p_object)); -} +void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { -bool Line2DEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Line2D"); + Node2D *node = _get_node(); + undo_redo->add_do_method(node, "set_points", p_polygon); + undo_redo->add_undo_method(node, "set_points", p_previous); } -void Line2DEditorPlugin::make_visible(bool p_visible) { - line2d_editor->set_visible(p_visible); - if (p_visible == false) - line2d_editor->edit(NULL); +Line2DEditor::Line2DEditor(EditorNode *p_editor) + : AbstractPolygon2DEditor(p_editor) { } -Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) { - editor = p_node; - line2d_editor = memnew(Line2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(line2d_editor); - line2d_editor->hide(); +Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) + : AbstractPolygon2DEditorPlugin(p_node, memnew(Line2DEditor(p_node)), "Line2D") { } diff --git a/editor/plugins/line_2d_editor_plugin.h b/editor/plugins/line_2d_editor_plugin.h index 6858680aed..24c19c420d 100644 --- a/editor/plugins/line_2d_editor_plugin.h +++ b/editor/plugins/line_2d_editor_plugin.h @@ -30,78 +30,34 @@ #ifndef LINE_2D_EDITOR_PLUGIN_H #define LINE_2D_EDITOR_PLUGIN_H -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" +#include "editor/plugins/abstract_polygon_2d_editor.h" #include "scene/2d/line_2d.h" -#include "scene/2d/path_2d.h" -#include "scene/gui/tool_button.h" -class CanvasItemEditor; +class Line2DEditor : public AbstractPolygon2DEditor { -class Line2DEditor : public HBoxContainer { - GDCLASS(Line2DEditor, HBoxContainer) -private: - void _mode_selected(int p_mode); - void _node_visibility_changed(); + GDCLASS(Line2DEditor, AbstractPolygon2DEditor); - int get_point_index_at(const Transform2D &xform, Vector2 gpos); - - UndoRedo *undo_redo; - - CanvasItemEditor *canvas_item_editor; - EditorNode *editor; - Panel *panel; Line2D *node; - HBoxContainer *base_hb; - Separator *sep; - - enum Mode { - MODE_CREATE = 0, - MODE_EDIT, - MODE_DELETE, - _MODE_COUNT - }; - - Mode mode; - ToolButton *toolbar_buttons[_MODE_COUNT]; - - bool _dragging; - int action_point; - Point2 moving_from; - Point2 moving_screen_from; - protected: - void _node_removed(Node *p_node); - void _notification(int p_what); + virtual Node2D *_get_node() const; + virtual void _set_node(Node *p_line); - static void _bind_methods(); + virtual bool _is_line() const; + virtual Variant _get_polygon(int p_idx) const; + virtual void _set_polygon(int p_idx, const Variant &p_polygon) const; + virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon); public: - bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_canvas(Control *p_canvas); - void edit(Node *p_line2d); Line2DEditor(EditorNode *p_editor); }; -class Line2DEditorPlugin : public EditorPlugin { - GDCLASS(Line2DEditorPlugin, EditorPlugin) - -public: - virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return line2d_editor->forward_canvas_gui_input(p_event); } - virtual void forward_draw_over_canvas(Control *p_canvas) { return line2d_editor->forward_draw_over_canvas(p_canvas); } +class Line2DEditorPlugin : public AbstractPolygon2DEditorPlugin { - virtual String get_name() const { return "Line2D"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); + GDCLASS(Line2DEditorPlugin, AbstractPolygon2DEditorPlugin); +public: Line2DEditorPlugin(EditorNode *p_node); - -private: - Line2DEditor *line2d_editor; - EditorNode *editor; }; #endif // LINE_2D_EDITOR_PLUGIN_H diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index f01d9367d2..cfc0741318 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -6,7 +6,6 @@ javascript_files = [ "os_javascript.cpp", "audio_driver_javascript.cpp", "javascript_main.cpp", - "audio_server_javascript.cpp", "power_javascript.cpp", "javascript_eval.cpp", ] @@ -19,7 +18,7 @@ javascript_objects = [] for x in javascript_files: javascript_objects.append(env_javascript.Object(x)) -env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_audio_server_mix_function','_main_after_fs_sync','_send_notification']\""]) +env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_main_after_fs_sync','_send_notification']\""]) # output file name without file extension basename = "godot" + env["PROGSUFFIX"] diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index cd3974669f..9633472cd2 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -30,29 +30,19 @@ #include "audio_driver_javascript.h" #include <emscripten.h> -#include <string.h> - -#define MAX_NUMBER_INTERFACES 3 -#define MAX_NUMBER_OUTPUT_DEVICES 6 - -/* Structure for passing information to callback function */ - -//AudioDriverJavaScript* AudioDriverJavaScript::s_ad=NULL; AudioDriverJavaScript *AudioDriverJavaScript::singleton_js = NULL; + const char *AudioDriverJavaScript::get_name() const { return "JavaScript"; } -extern "C" { - -void js_audio_driver_mix_function(int p_frames) { +extern "C" EMSCRIPTEN_KEEPALIVE void js_audio_driver_mix_function(int p_frames) { //print_line("MIXI! "+itos(p_frames)); AudioDriverJavaScript::singleton_js->mix_to_js(p_frames); } -} void AudioDriverJavaScript::mix_to_js(int p_frames) { @@ -65,11 +55,11 @@ void AudioDriverJavaScript::mix_to_js(int p_frames) { audio_server_process(p_frames, stream_buffer); for (int i = 0; i < tomix * internal_buffer_channels; i++) { - internal_buffer[i] = float(stream_buffer[i] >> 16) * 32768.0; + internal_buffer[i] = float(stream_buffer[i] >> 16) / 32768.0; } /* clang-format off */ - EM_ASM_({ + EM_ASM_ARGS({ var data = HEAPF32.subarray($0 / 4, $0 / 4 + $2 * 2); for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) { @@ -95,29 +85,24 @@ Error AudioDriverJavaScript::init() { void AudioDriverJavaScript::start() { - internal_buffer_channels = 2; internal_buffer = memnew_arr(float, INTERNAL_BUFFER_SIZE *internal_buffer_channels); stream_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE * 4); //max 4 channels /* clang-format off */ - EM_ASM( - _as_audioctx = new (window.AudioContext || window.webkitAudioContext)(); - - audio_server_mix_function = Module.cwrap('js_audio_driver_mix_function', 'void', ['number']); - ); - - int buffer_latency = 16384; - EM_ASM_( { - _as_script_node = _as_audioctx.createScriptProcessor($0, 0, 2); + mix_rate = EM_ASM_INT({ + _as_audioctx = new (window.AudioContext || window.webkitAudioContext); + _as_script_node = _as_audioctx.createScriptProcessor($0, 0, $1); _as_script_node.connect(_as_audioctx.destination); console.log(_as_script_node.bufferSize); + var jsAudioDriverMixFunction = cwrap('js_audio_driver_mix_function', null, ['number']); _as_script_node.onaudioprocess = function(audioProcessingEvent) { - // The output buffer contains the samples that will be modified and played + // The output buffer contains the samples that will be modified and played _as_output_buffer = audioProcessingEvent.outputBuffer; - audio_server_mix_function(_as_output_buffer.getChannelData(0).length); - } - }, buffer_latency); + jsAudioDriverMixFunction([_as_output_buffer.getChannelData(0).length]); + }; + return _as_audioctx.sampleRate; + }, INTERNAL_BUFFER_SIZE, internal_buffer_channels); /* clang-format on */ } @@ -152,6 +137,7 @@ void AudioDriverJavaScript::finish() { AudioDriverJavaScript::AudioDriverJavaScript() { - mix_rate = 44100; + internal_buffer_channels = 2; + mix_rate = DEFAULT_MIX_RATE; singleton_js = this; } diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h index c3adeca07b..b265c4e030 100644 --- a/platform/javascript/audio_driver_javascript.h +++ b/platform/javascript/audio_driver_javascript.h @@ -32,20 +32,15 @@ #include "servers/audio_server.h" -#include "os/mutex.h" - class AudioDriverJavaScript : public AudioDriver { enum { INTERNAL_BUFFER_SIZE = 4096, - STREAM_SCALE_BITS = 12 - }; int mix_rate; float *internal_buffer; int internal_buffer_channels; - int internal_buffer_size; int32_t *stream_buffer; public: diff --git a/platform/javascript/audio_server_javascript.cpp b/platform/javascript/audio_server_javascript.cpp deleted file mode 100644 index ab9f66ce5b..0000000000 --- a/platform/javascript/audio_server_javascript.cpp +++ /dev/null @@ -1,853 +0,0 @@ -/*************************************************************************/ -/* audio_server_javascript.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "audio_server_javascript.h" - -// FIXME: Needs to be ported to the new AudioServer API in 3.0 -#if 0 -#include "emscripten.h" - -AudioMixer *AudioServerJavascript::get_mixer() { - - return NULL; -} - -void AudioServerJavascript::audio_mixer_chunk_callback(int p_frames){ - - -} - - -RID AudioServerJavascript::sample_create(SampleFormat p_format, bool p_stereo, int p_length) { - - Sample *sample = memnew( Sample ); - sample->format=p_format; - sample->stereo=p_stereo; - sample->length=p_length; - sample->loop_begin=0; - sample->loop_end=p_length; - sample->loop_format=SAMPLE_LOOP_NONE; - sample->mix_rate=44100; - sample->index=-1; - - return sample_owner.make_rid(sample); - -} - -void AudioServerJavascript::sample_set_description(RID p_sample, const String& p_description){ - - -} -String AudioServerJavascript::sample_get_description(RID p_sample) const{ - - return String(); -} - -AudioServerJavascript::SampleFormat AudioServerJavascript::sample_get_format(RID p_sample) const{ - - return SAMPLE_FORMAT_PCM8; -} -bool AudioServerJavascript::sample_is_stereo(RID p_sample) const{ - - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,false); - return sample->stereo; - -} -int AudioServerJavascript::sample_get_length(RID p_sample) const{ - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,0); - return sample->length; -} -const void* AudioServerJavascript::sample_get_data_ptr(RID p_sample) const{ - - return NULL; -} - -void AudioServerJavascript::sample_set_data(RID p_sample, const PoolVector<uint8_t>& p_buffer){ - - Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - int chans = sample->stereo?2:1; - - Vector<float> buffer; - buffer.resize(sample->length*chans); - PoolVector<uint8_t>::Read r=p_buffer.read(); - if (sample->format==SAMPLE_FORMAT_PCM8) { - const int8_t*ptr = (const int8_t*)r.ptr(); - for(int i=0;i<sample->length*chans;i++) { - buffer[i]=ptr[i]/128.0; - } - } else if (sample->format==SAMPLE_FORMAT_PCM16){ - const int16_t*ptr = (const int16_t*)r.ptr(); - for(int i=0;i<sample->length*chans;i++) { - buffer[i]=ptr[i]/32768.0; - } - } else { - ERR_EXPLAIN("Unsupported for now"); - ERR_FAIL(); - } - - sample->tmp_data=buffer; - - - -} -PoolVector<uint8_t> AudioServerJavascript::sample_get_data(RID p_sample) const{ - - - return PoolVector<uint8_t>(); -} - -void AudioServerJavascript::sample_set_mix_rate(RID p_sample,int p_rate){ - Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - sample->mix_rate=p_rate; - -} - -int AudioServerJavascript::sample_get_mix_rate(RID p_sample) const{ - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,0); - return sample->mix_rate; -} - - -void AudioServerJavascript::sample_set_loop_format(RID p_sample,SampleLoopFormat p_format){ - - Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - sample->loop_format=p_format; - -} - -AudioServerJavascript::SampleLoopFormat AudioServerJavascript::sample_get_loop_format(RID p_sample) const { - - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,SAMPLE_LOOP_NONE); - return sample->loop_format; -} - -void AudioServerJavascript::sample_set_loop_begin(RID p_sample,int p_pos){ - - Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - sample->loop_begin=p_pos; - -} -int AudioServerJavascript::sample_get_loop_begin(RID p_sample) const{ - - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,0); - return sample->loop_begin; -} - -void AudioServerJavascript::sample_set_loop_end(RID p_sample,int p_pos){ - - Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - sample->loop_end=p_pos; - -} -int AudioServerJavascript::sample_get_loop_end(RID p_sample) const{ - - const Sample *sample = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!sample,0); - return sample->loop_end; -} - - -/* VOICE API */ - -RID AudioServerJavascript::voice_create(){ - - Voice *voice = memnew( Voice ); - - voice->index=voice_base; - voice->volume=1.0; - voice->pan=0.0; - voice->pan_depth=.0; - voice->pan_height=0.0; - voice->chorus=0; - voice->reverb_type=REVERB_SMALL; - voice->reverb=0; - voice->mix_rate=-1; - voice->positional=false; - voice->active=false; - - /* clang-format off */ - EM_ASM_( { - _as_voices[$0] = null; - _as_voice_gain[$0] = _as_audioctx.createGain(); - _as_voice_pan[$0] = _as_audioctx.createStereoPanner(); - _as_voice_gain[$0].connect(_as_voice_pan[$0]); - _as_voice_pan[$0].connect(_as_audioctx.destination); - }, voice_base); - /* clang-format on */ - - voice_base++; - - return voice_owner.make_rid( voice ); -} - -void AudioServerJavascript::voice_play(RID p_voice, RID p_sample){ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND(!voice); - Sample *sample=sample_owner.get(p_sample); - ERR_FAIL_COND(!sample); - - // due to how webaudio works, sample cration is deferred until used - // sorry! WebAudio absolutely sucks - - - if (sample->index==-1) { - //create sample if not created - ERR_FAIL_COND(sample->tmp_data.size()==0); - sample->index=sample_base; - /* clang-format off */ - EM_ASM_({ - _as_samples[$0] = _as_audioctx.createBuffer($1, $2, $3); - }, sample_base, sample->stereo ? 2 : 1, sample->length, sample->mix_rate); - /* clang-format on */ - - sample_base++; - int chans = sample->stereo?2:1; - - - for(int i=0;i<chans;i++) { - /* clang-format off */ - EM_ASM_({ - _as_edited_buffer = _as_samples[$0].getChannelData($1); - }, sample->index, i); - /* clang-format on */ - - for(int j=0;j<sample->length;j++) { - /* clang-format off */ - EM_ASM_({ - _as_edited_buffer[$0] = $1; - }, j, sample->tmp_data[j * chans + i]); - /* clang-format on */ - } - } - - sample->tmp_data.clear(); - } - - - voice->sample_mix_rate=sample->mix_rate; - if (voice->mix_rate==-1) { - voice->mix_rate=voice->sample_mix_rate; - } - - float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0); - int detune = int(freq_diff*1200.0); - - /* clang-format off */ - EM_ASM_({ - if (_as_voices[$0] !== null) { - _as_voices[$0].stop(); //stop and byebye - } - _as_voices[$0] = _as_audioctx.createBufferSource(); - _as_voices[$0].connect(_as_voice_gain[$0]); - _as_voices[$0].buffer = _as_samples[$1]; - _as_voices[$0].loopStart.value = $1; - _as_voices[$0].loopEnd.value = $2; - _as_voices[$0].loop.value = $3; - _as_voices[$0].detune.value = $6; - _as_voice_pan[$0].pan.value = $4; - _as_voice_gain[$0].gain.value = $5; - _as_voices[$0].start(); - _as_voices[$0].onended = function() { - _as_voices[$0].disconnect(_as_voice_gain[$0]); - _as_voices[$0] = null; - } - }, voice->index, sample->index, sample->mix_rate * sample->loop_begin, sample->mix_rate * sample->loop_end, sample->loop_format != SAMPLE_LOOP_NONE, voice->pan, voice->volume * fx_volume_scale, detune); - /* clang-format on */ - - voice->active=true; -} - -void AudioServerJavascript::voice_set_volume(RID p_voice, float p_volume){ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND(!voice); - - voice->volume=p_volume; - - if (voice->active) { - /* clang-format off */ - EM_ASM_({ - _as_voice_gain[$0].gain.value = $1; - }, voice->index, voice->volume * fx_volume_scale); - /* clang-format on */ - } - -} -void AudioServerJavascript::voice_set_pan(RID p_voice, float p_pan, float p_depth,float height){ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND(!voice); - - voice->pan=p_pan; - voice->pan_depth=p_depth; - voice->pan_height=height; - - if (voice->active) { - /* clang-format off */ - EM_ASM_({ - _as_voice_pan[$0].pan.value = $1; - }, voice->index, voice->pan); - /* clang-format on */ - } -} -void AudioServerJavascript::voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain){ - -} -void AudioServerJavascript::voice_set_chorus(RID p_voice, float p_chorus ){ - -} -void AudioServerJavascript::voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb){ - -} -void AudioServerJavascript::voice_set_mix_rate(RID p_voice, int p_mix_rate){ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND(!voice); - - voice->mix_rate=p_mix_rate; - - if (voice->active) { - - float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0); - int detune = int(freq_diff*1200.0); - /* clang-format off */ - EM_ASM_({ - _as_voices[$0].detune.value = $1; - }, voice->index, detune); - /* clang-format on */ - } -} -void AudioServerJavascript::voice_set_positional(RID p_voice, bool p_positional){ - -} - -float AudioServerJavascript::voice_get_volume(RID p_voice) const{ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND_V(!voice,0); - - return voice->volume; -} -float AudioServerJavascript::voice_get_pan(RID p_voice) const{ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND_V(!voice,0); - - return voice->pan; -} -float AudioServerJavascript::voice_get_pan_depth(RID p_voice) const{ - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND_V(!voice,0); - - return voice->pan_depth; -} -float AudioServerJavascript::voice_get_pan_height(RID p_voice) const{ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND_V(!voice,0); - - return voice->pan_height; -} -AudioServerJavascript::FilterType AudioServerJavascript::voice_get_filter_type(RID p_voice) const{ - - return FILTER_NONE; -} -float AudioServerJavascript::voice_get_filter_cutoff(RID p_voice) const{ - - return 0; -} -float AudioServerJavascript::voice_get_filter_resonance(RID p_voice) const{ - - return 0; -} -float AudioServerJavascript::voice_get_chorus(RID p_voice) const{ - - return 0; -} -AudioServerJavascript::ReverbRoomType AudioServerJavascript::voice_get_reverb_type(RID p_voice) const{ - - return REVERB_SMALL; -} -float AudioServerJavascript::voice_get_reverb(RID p_voice) const{ - - return 0; -} - -int AudioServerJavascript::voice_get_mix_rate(RID p_voice) const{ - - return 44100; -} - -bool AudioServerJavascript::voice_is_positional(RID p_voice) const{ - - return false; -} - -void AudioServerJavascript::voice_stop(RID p_voice){ - - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND(!voice); - - if (voice->active) { - /* clang-format off */ - EM_ASM_({ - if (_as_voices[$0] !== null) { - _as_voices[$0].stop(); - _as_voices[$0].disconnect(_as_voice_gain[$0]); - _as_voices[$0] = null; - } - }, voice->index); - /* clang-format on */ - - voice->active=false; - } - - -} -bool AudioServerJavascript::voice_is_active(RID p_voice) const{ - Voice* voice=voice_owner.get(p_voice); - ERR_FAIL_COND_V(!voice,false); - - return voice->active; -} - -/* STREAM API */ - -RID AudioServerJavascript::audio_stream_create(AudioStream *p_stream) { - - - Stream *s = memnew(Stream); - s->audio_stream=p_stream; - s->event_stream=NULL; - s->active=false; - s->E=NULL; - s->volume_scale=1.0; - p_stream->set_mix_rate(webaudio_mix_rate); - - return stream_owner.make_rid(s); -} - -RID AudioServerJavascript::event_stream_create(EventStream *p_stream) { - - - Stream *s = memnew(Stream); - s->audio_stream=NULL; - s->event_stream=p_stream; - s->active=false; - s->E=NULL; - s->volume_scale=1.0; - //p_stream->set_mix_rate(AudioDriverJavascript::get_singleton()->get_mix_rate()); - - return stream_owner.make_rid(s); - - -} - - -void AudioServerJavascript::stream_set_active(RID p_stream, bool p_active) { - - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND(!s); - - if (s->active==p_active) - return; - - s->active=p_active; - if (p_active) - s->E=active_audio_streams.push_back(s); - else { - active_audio_streams.erase(s->E); - s->E=NULL; - } -} - -bool AudioServerJavascript::stream_is_active(RID p_stream) const { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND_V(!s,false); - return s->active; -} - -void AudioServerJavascript::stream_set_volume_scale(RID p_stream, float p_scale) { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND(!s); - s->volume_scale=p_scale; - -} - -float AudioServerJavascript::stream_set_volume_scale(RID p_stream) const { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND_V(!s,0); - return s->volume_scale; - -} - - -/* Audio Physics API */ - -void AudioServerJavascript::free(RID p_id){ - - if (voice_owner.owns(p_id)) { - Voice* voice=voice_owner.get(p_id); - ERR_FAIL_COND(!voice); - - if (voice->active) { - /* clang-format off */ - EM_ASM_({ - if (_as_voices[$0] !== null) { - _as_voices[$0].stop(); - _as_voices[$0].disconnect(_as_voice_gain[$0]); - } - }, voice->index); - /* clang-format on */ - } - - /* clang-format off */ - EM_ASM_({ - delete _as_voices[$0]; - _as_voice_gain[$0].disconnect(_as_voice_pan[$0]); - delete _as_voice_gain[$0]; - _as_voice_pan[$0].disconnect(_as_audioctx.destination); - delete _as_voice_pan[$0]; - }, voice->index); - /* clang-format on */ - - voice_owner.free(p_id); - memdelete(voice); - - } else if (sample_owner.owns(p_id)) { - - Sample *sample = sample_owner.get(p_id); - ERR_FAIL_COND(!sample); - - /* clang-format off */ - EM_ASM_({ - delete _as_samples[$0]; - }, sample->index); - /* clang-format on */ - - sample_owner.free(p_id); - memdelete(sample); - - } else if (stream_owner.owns(p_id)) { - - - Stream *s=stream_owner.get(p_id); - - if (s->active) { - stream_set_active(p_id,false); - } - - memdelete(s); - stream_owner.free(p_id); - } -} - -extern "C" { - - -void audio_server_mix_function(int p_frames) { - - //print_line("MIXI! "+itos(p_frames)); - static_cast<AudioServerJavascript*>(AudioServerJavascript::get_singleton())->mix_to_js(p_frames); -} - -} - -void AudioServerJavascript::mix_to_js(int p_frames) { - - - //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE - int todo=p_frames; - int offset=0; - - while(todo) { - - int tomix=MIN(todo,INTERNAL_BUFFER_SIZE); - driver_process_chunk(tomix); - - /* clang-format off */ - EM_ASM_({ - var data = HEAPF32.subarray($0 / 4, $0 / 4 + $2 * 2); - - for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) { - var outputData = _as_output_buffer.getChannelData(channel); - // Loop through samples - for (var sample = 0; sample < $2; sample++) { - // make output equal to the same as the input - outputData[sample + $1] = data[sample * 2 + channel]; - } - } - }, internal_buffer, offset, tomix); - /* clang-format on */ - - todo-=tomix; - offset+=tomix; - } -} - -void AudioServerJavascript::init(){ - - /* - // clang-format off - EM_ASM( - console.log('server is ' + audio_server); - ); - // clang-format on - */ - - - //int latency = GLOBAL_DEF("javascript/audio_latency",16384); - - internal_buffer_channels=2; - internal_buffer = memnew_arr(float,INTERNAL_BUFFER_SIZE*internal_buffer_channels); - stream_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*4); //max 4 channels - - stream_volume=0.3; - - int buffer_latency=16384; - - /* clang-format off */ - EM_ASM_( { - _as_script_node = _as_audioctx.createScriptProcessor($0, 0, 2); - _as_script_node.connect(_as_audioctx.destination); - console.log(_as_script_node.bufferSize); - - _as_script_node.onaudioprocess = function(audioProcessingEvent) { - // The output buffer contains the samples that will be modified and played - _as_output_buffer = audioProcessingEvent.outputBuffer; - audio_server_mix_function(_as_output_buffer.getChannelData(0).length); - } - }, buffer_latency); - /* clang-format on */ - - -} - -void AudioServerJavascript::finish(){ - -} -void AudioServerJavascript::update(){ - - for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback - - List<Stream*>::Element *N=E->next(); - - if (E->get()->audio_stream) - E->get()->audio_stream->update(); - - E=N; - } -} - -/* MISC config */ - -void AudioServerJavascript::lock(){ - -} -void AudioServerJavascript::unlock(){ - -} -int AudioServerJavascript::get_default_channel_count() const{ - - return 1; -} -int AudioServerJavascript::get_default_mix_rate() const{ - - return 44100; -} - -void AudioServerJavascript::set_stream_global_volume_scale(float p_volume){ - - stream_volume_scale=p_volume; -} -void AudioServerJavascript::set_fx_global_volume_scale(float p_volume){ - - fx_volume_scale=p_volume; -} -void AudioServerJavascript::set_event_voice_global_volume_scale(float p_volume){ - -} - -float AudioServerJavascript::get_stream_global_volume_scale() const{ - return 1; -} -float AudioServerJavascript::get_fx_global_volume_scale() const{ - - return 1; -} -float AudioServerJavascript::get_event_voice_global_volume_scale() const{ - - return 1; -} - -uint32_t AudioServerJavascript::read_output_peak() const{ - - return 0; -} - -AudioServerJavascript *AudioServerJavascript::singleton=NULL; - -AudioServer *AudioServerJavascript::get_singleton() { - return singleton; -} - -double AudioServerJavascript::get_mix_time() const{ - - return 0; -} -double AudioServerJavascript::get_output_delay() const { - - return 0; -} - - -void AudioServerJavascript::driver_process_chunk(int p_frames) { - - - - int samples=p_frames*internal_buffer_channels; - - for(int i=0;i<samples;i++) { - internal_buffer[i]=0; - } - - - for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) { - - ERR_CONTINUE(!E->get()->active); // bug? - - - AudioStream *as=E->get()->audio_stream; - if (!as) - continue; - - int channels=as->get_channel_count(); - if (channels==0) - continue; // does not want mix - if (!as->mix(stream_buffer,p_frames)) - continue; //nothing was mixed!! - - int32_t stream_vol_scale=(stream_volume*stream_volume_scale*E->get()->volume_scale)*(1<<STREAM_SCALE_BITS); - -#define STRSCALE(m_val) ((((m_val >> STREAM_SCALE_BITS) * stream_vol_scale) >> 8) / 8388608.0) - switch(channels) { - case 1: { - - for(int i=0;i<p_frames;i++) { - - internal_buffer[(i<<1)+0]+=STRSCALE(stream_buffer[i]); - internal_buffer[(i<<1)+1]+=STRSCALE(stream_buffer[i]); - } - } break; - case 2: { - - for(int i=0;i<p_frames*2;i++) { - - internal_buffer[i]+=STRSCALE(stream_buffer[i]); - } - } break; - case 4: { - - for(int i=0;i<p_frames;i++) { - - internal_buffer[(i<<2)+0]+=STRSCALE((stream_buffer[(i<<2)+0]+stream_buffer[(i<<2)+2])>>1); - internal_buffer[(i<<2)+1]+=STRSCALE((stream_buffer[(i<<2)+1]+stream_buffer[(i<<2)+3])>>1); - } - } break; - - - } - -#undef STRSCALE - } -} - - -/*void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) { - - - _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate()); - //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE - int todo=p_frames; - while(todo) { - - int tomix=MIN(todo,INTERNAL_BUFFER_SIZE); - driver_process_chunk(tomix,p_buffer); - p_buffer+=tomix; - todo-=tomix; - } - - -}*/ - -AudioServerJavascript::AudioServerJavascript() { - - singleton=this; - sample_base=1; - voice_base=1; - /* clang-format off */ - EM_ASM( - _as_samples = {}; - _as_voices = {}; - _as_voice_pan = {}; - _as_voice_gain = {}; - - _as_audioctx = new (window.AudioContext || window.webkitAudioContext)(); - - audio_server_mix_function = Module.cwrap('audio_server_mix_function', 'void', ['number']); - ); - /* clang-format on */ - - /* clang-format off */ - webaudio_mix_rate = EM_ASM_INT_V( - return _as_audioctx.sampleRate; - ); - /* clang-format on */ - print_line("WEBAUDIO MIX RATE: "+itos(webaudio_mix_rate)); - event_voice_scale=1.0; - fx_volume_scale=1.0; - stream_volume_scale=1.0; - -} -#endif diff --git a/platform/javascript/audio_server_javascript.h b/platform/javascript/audio_server_javascript.h deleted file mode 100644 index 0773459f56..0000000000 --- a/platform/javascript/audio_server_javascript.h +++ /dev/null @@ -1,229 +0,0 @@ -/*************************************************************************/ -/* audio_server_javascript.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_SERVER_JAVASCRIPT_H -#define AUDIO_SERVER_JAVASCRIPT_H - -// FIXME: Needs to be ported to the new AudioServer API in 3.0 -#if 0 -#include "servers/audio_server.h" - -class AudioServerJavascript : public AudioServer { - - GDCLASS(AudioServerJavascript,AudioServer); - - enum { - INTERNAL_BUFFER_SIZE=4096, - STREAM_SCALE_BITS=12 - - }; - - AudioMixer *get_mixer(); - void audio_mixer_chunk_callback(int p_frames); - - struct Sample { - SampleFormat format; - SampleLoopFormat loop_format; - int loop_begin; - int loop_end; - int length; - int index; - int mix_rate; - bool stereo; - - Vector<float> tmp_data; - }; - - mutable RID_Owner<Sample> sample_owner; - int sample_base; - - struct Voice { - int index; - float volume; - float pan; - float pan_depth; - float pan_height; - - float chorus; - ReverbRoomType reverb_type; - float reverb; - - int mix_rate; - int sample_mix_rate; - bool positional; - - bool active; - - }; - - mutable RID_Owner<Voice> voice_owner; - - int voice_base; - - struct Stream { - bool active; - List<Stream*>::Element *E; - AudioStream *audio_stream; - EventStream *event_stream; - float volume_scale; - }; - - List<Stream*> active_audio_streams; - - //List<Stream*> event_streams; - - float * internal_buffer; - int internal_buffer_channels; - int32_t * stream_buffer; - - mutable RID_Owner<Stream> stream_owner; - - float stream_volume; - float stream_volume_scale; - - float event_voice_scale; - float fx_volume_scale; - - - void driver_process_chunk(int p_frames); - - int webaudio_mix_rate; - - - static AudioServerJavascript *singleton; -public: - - void mix_to_js(int p_frames); - /* SAMPLE API */ - - virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length); - - virtual void sample_set_description(RID p_sample, const String& p_description); - virtual String sample_get_description(RID p_sample) const; - - virtual SampleFormat sample_get_format(RID p_sample) const; - virtual bool sample_is_stereo(RID p_sample) const; - virtual int sample_get_length(RID p_sample) const; - virtual const void* sample_get_data_ptr(RID p_sample) const; - - - virtual void sample_set_data(RID p_sample, const PoolVector<uint8_t>& p_buffer); - virtual PoolVector<uint8_t> sample_get_data(RID p_sample) const; - - virtual void sample_set_mix_rate(RID p_sample,int p_rate); - virtual int sample_get_mix_rate(RID p_sample) const; - - virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format); - virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const; - - virtual void sample_set_loop_begin(RID p_sample,int p_pos); - virtual int sample_get_loop_begin(RID p_sample) const; - - virtual void sample_set_loop_end(RID p_sample,int p_pos); - virtual int sample_get_loop_end(RID p_sample) const; - - - /* VOICE API */ - - virtual RID voice_create(); - - virtual void voice_play(RID p_voice, RID p_sample); - - virtual void voice_set_volume(RID p_voice, float p_volume); - virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1 - virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=0); - virtual void voice_set_chorus(RID p_voice, float p_chorus ); - virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb); - virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate); - virtual void voice_set_positional(RID p_voice, bool p_positional); - - virtual float voice_get_volume(RID p_voice) const; - virtual float voice_get_pan(RID p_voice) const; //pan and depth go from -1 to 1 - virtual float voice_get_pan_depth(RID p_voice) const; //pan and depth go from -1 to 1 - virtual float voice_get_pan_height(RID p_voice) const; //pan and depth go from -1 to 1 - virtual FilterType voice_get_filter_type(RID p_voice) const; - virtual float voice_get_filter_cutoff(RID p_voice) const; - virtual float voice_get_filter_resonance(RID p_voice) const; - virtual float voice_get_chorus(RID p_voice) const; - virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const; - virtual float voice_get_reverb(RID p_voice) const; - - virtual int voice_get_mix_rate(RID p_voice) const; - virtual bool voice_is_positional(RID p_voice) const; - - virtual void voice_stop(RID p_voice); - virtual bool voice_is_active(RID p_voice) const; - - /* STREAM API */ - - virtual RID audio_stream_create(AudioStream *p_stream); - virtual RID event_stream_create(EventStream *p_stream); - - virtual void stream_set_active(RID p_stream, bool p_active); - virtual bool stream_is_active(RID p_stream) const; - - virtual void stream_set_volume_scale(RID p_stream, float p_scale); - virtual float stream_set_volume_scale(RID p_stream) const; - - /* Audio Physics API */ - - virtual void free(RID p_id); - - virtual void init(); - virtual void finish(); - virtual void update(); - - /* MISC config */ - - virtual void lock(); - virtual void unlock(); - virtual int get_default_channel_count() const; - virtual int get_default_mix_rate() const; - - virtual void set_stream_global_volume_scale(float p_volume); - virtual void set_fx_global_volume_scale(float p_volume); - virtual void set_event_voice_global_volume_scale(float p_volume); - - virtual float get_stream_global_volume_scale() const; - virtual float get_fx_global_volume_scale() const; - virtual float get_event_voice_global_volume_scale() const; - - virtual uint32_t read_output_peak() const; - - static AudioServer *get_singleton(); - - virtual double get_mix_time() const; //useful for video -> audio sync - virtual double get_output_delay() const; - - - AudioServerJavascript(); -}; - -#endif // AUDIO_SERVER_JAVASCRIPT_H -#endif diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 908a252905..07720e95ec 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -31,7 +31,6 @@ #define OS_JAVASCRIPT_H #include "audio_driver_javascript.h" -#include "audio_server_javascript.h" #include "drivers/unix/os_unix.h" #include "javascript_eval.h" #include "main/input_default.h" |