diff options
-rw-r--r-- | core/math/a_star.cpp | 22 | ||||
-rw-r--r-- | doc/classes/Input.xml | 2 | ||||
-rw-r--r-- | doc/tools/makemd.py | 360 | ||||
-rw-r--r-- | editor/icons/icon_GUI_viewport_hdiagsplitter.svg | 64 | ||||
-rw-r--r-- | editor/icons/icon_GUI_viewport_vdiagsplitter.svg | 68 | ||||
-rw-r--r-- | editor/icons/icon_GUI_viewport_vhsplitter.svg | 63 | ||||
-rw-r--r-- | editor/plugins/spatial_editor_plugin.cpp | 154 | ||||
-rw-r--r-- | editor/plugins/spatial_editor_plugin.h | 5 | ||||
-rw-r--r-- | main/tests/test_astar.cpp | 117 | ||||
-rw-r--r-- | main/tests/test_astar.h | 41 | ||||
-rw-r--r-- | main/tests/test_main.cpp | 7 | ||||
-rw-r--r-- | scene/gui/spin_box.cpp | 13 | ||||
-rw-r--r-- | scene/gui/spin_box.h | 3 |
13 files changed, 484 insertions, 435 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index e4f93289e9..451c45cade 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -250,14 +250,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { n->distance = _compute_cost(begin_point->id, n->id) * n->weight_scale; n->last_pass = pass; open_list.add(&n->list); - - if (end_point == n) { - found_route = true; - break; - } } - while (!found_route) { + while (true) { if (open_list.first() == NULL) { // No path found @@ -277,13 +272,16 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { cost += _estimate_cost(p->id, end_point->id); if (cost < least_cost) { - least_cost_point = E; least_cost = cost; } } Point *p = least_cost_point->self(); + if (p == end_point) { + found_route = true; + break; + } for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { @@ -295,7 +293,6 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { // Already visited, is this cheaper? if (e->distance > distance) { - e->prev_point = p; e->distance = distance; } @@ -306,18 +303,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { e->distance = distance; e->last_pass = pass; // Mark as used open_list.add(&e->list); - - if (e == end_point) { - // End reached; stop algorithm - found_route = true; - break; - } } } - if (found_route) - break; - open_list.remove(least_cost_point); } diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index a0d6d29be6..338d01ae5f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -390,7 +390,7 @@ Pointing hand cursor. Usually used to indicate the pointer is over a link or other interactable item. </constant> <constant name="CURSOR_CROSS" value="3" enum="CursorShape"> - Cross cursor. Typically appears over regions in which a drawing operation can be performance or for selections. + Cross cursor. Typically appears over regions in which a drawing operation can be performed or for selections. </constant> <constant name="CURSOR_WAIT" value="4" enum="CursorShape"> Wait cursor. Indicates that the application is busy performing an operation. diff --git a/doc/tools/makemd.py b/doc/tools/makemd.py deleted file mode 100644 index 056f1ca82d..0000000000 --- a/doc/tools/makemd.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import sys -import os.path as path -import os -import xml.etree.ElementTree as ET - -input_list = [] - -for arg in sys.argv[1:]: - if not path.exists(arg): - exit("path {} doesn't exist".format(arg)) - elif path.isdir(arg): - input_list += filter(path.isfile, [path.join(arg, f) for f in os.listdir(arg)]) - else: # assuming is a file - input_list.append(arg) - -if len(input_list) < 1: - print 'usage: makemd.py <classes.xml>' - sys.exit(0) - - -def validate_tag(elem, tag): - if elem.tag != tag: - print "Tag mismatch, expected '" + tag + "', got " + elem.tag - sys.exit(255) - - -class_names = [] -classes = {} - - -def make_class_list(class_list, columns): - - f = open('class_list.md', 'wb') - prev = 0 - col_max = len(class_list) / columns + 1 - col_count = 0 - row_count = 0 - last_initial = '' - fit_columns = [] - - for n in range(0, columns): - fit_columns += [[]] - - indexers = [] - last_initial = '' - - idx = 0 - for n in class_list: - col = idx / col_max - if col >= columns: - col = columns - 1 - fit_columns[col] += [n] - idx += 1 - if n[:1] != last_initial: - indexers += [n] - last_initial = n[:1] - - row_max = 0 - f.write("\n") - - for n in range(0, columns): - if len(fit_columns[n]) > row_max: - row_max = len(fit_columns[n]) - - f.write("| ") - for n in range(0, columns): - f.write(" | |") - - f.write("\n") - f.write("| ") - for n in range(0, columns): - f.write(" --- | ------- |") - f.write("\n") - - for r in range(0, row_max): - s = '| ' - for c in range(0, columns): - if r >= len(fit_columns[c]): - continue - - classname = fit_columns[c][r] - initial = classname[0] - if classname in indexers: - s += '**' + initial + '** | ' - else: - s += ' | ' - - s += '[' + classname + '](class_' + classname.lower() + ') | ' - - s += '\n' - f.write(s) - - f.close() - - -def dokuize_text(txt): - - return txt - - -def dokuize_text(text): - pos = 0 - while True: - pos = text.find('[', pos) - if pos == -1: - break - - endq_pos = text.find(']', pos + 1) - if endq_pos == -1: - break - - pre_text = text[:pos] - post_text = text[endq_pos + 1:] - tag_text = text[pos + 1:endq_pos] - - if tag_text in class_names: - tag_text = make_type(tag_text) - else: - - # command - - cmd = tag_text - space_pos = tag_text.find(' ') - if cmd.find('html') == 0: - cmd = tag_text[:space_pos] - param = tag_text[space_pos + 1:] - tag_text = '<' + param + '>' - elif cmd.find('method') == 0: - cmd = tag_text[:space_pos] - param = tag_text[space_pos + 1:] - - if param.find('.') != -1: - (class_param, method_param) = param.split('.') - tag_text = '[' + class_param + '.' + method_param.replace("_", "_") + '](' + class_param.lower() + '#' \ - + method_param + ')' - else: - tag_text = '[' + param.replace("_", "_") + '](#' + param + ')' - elif cmd.find('image=') == 0: - tag_text = '' - elif cmd.find('url=') == 0: - tag_text = '[' + cmd[4:] + '](' + cmd[4:] - elif cmd == '/url': - tag_text = ')' - elif cmd == 'center': - tag_text = '' - elif cmd == '/center': - tag_text = '' - elif cmd == 'br': - tag_text = '\n' - elif cmd == 'i' or cmd == '/i': - tag_text = '_' - elif cmd == 'b' or cmd == '/b': - tag_text = '**' - elif cmd == 'u' or cmd == '/u': - tag_text = '__' - else: - tag_text = '[' + tag_text + ']' - - text = pre_text + tag_text + post_text - pos = len(pre_text) + len(tag_text) - - # tnode = ET.SubElement(parent,"div") - # tnode.text=text - - return text - - -def make_type(t): - global class_names - if t in class_names: - return '[' + t + '](class_' + t.lower() + ')' - return t - - -def make_method( - f, - name, - m, - declare, - event=False, -): - - s = ' * ' - ret_type = 'void' - args = list(m) - mdata = {} - mdata['argidx'] = [] - for a in args: - if a.tag == 'return': - idx = -1 - elif a.tag == 'argument': - idx = int(a.attrib['index']) - else: - continue - - mdata['argidx'].append(idx) - mdata[idx] = a - - if not event: - if -1 in mdata['argidx']: - s += make_type(mdata[-1].attrib['type']) - else: - s += 'void' - s += ' ' - - if declare: - - # span.attrib["class"]="funcdecl" - # a=ET.SubElement(span,"a") - # a.attrib["name"]=name+"_"+m.attrib["name"] - # a.text=name+"::"+m.attrib["name"] - - s += ' **' + m.attrib['name'].replace("_", "_") + '** ' - else: - s += ' **[' + m.attrib['name'].replace("_", "_") + '](#' + m.attrib['name'] + ')** ' - - s += ' **(**' - argfound = False - for a in mdata['argidx']: - arg = mdata[a] - if a < 0: - continue - if a > 0: - s += ', ' - else: - s += ' ' - - s += make_type(arg.attrib['type']) - if 'name' in arg.attrib: - s += ' ' + arg.attrib['name'] - else: - s += ' arg' + str(a) - - if 'default' in arg.attrib: - s += '=' + arg.attrib['default'] - - argfound = True - - if argfound: - s += ' ' - s += ' **)**' - - if 'qualifiers' in m.attrib: - s += ' ' + m.attrib['qualifiers'] - - f.write(s + '\n') - - -def make_doku_class(node): - - name = node.attrib['name'] - - f = open("class_" + name.lower() + '.md', 'wb') - - f.write('# ' + name + ' \n') - - if 'inherits' in node.attrib: - inh = node.attrib['inherits'].strip() - f.write('####**Inherits:** ' + make_type(inh) + '\n') - if 'category' in node.attrib: - f.write('####**Category:** ' + node.attrib['category'].strip() - + '\n') - - briefd = node.find('brief_description') - if briefd != None: - f.write('\n### Brief Description \n') - f.write(dokuize_text(briefd.text.strip()) + '\n') - - methods = node.find('methods') - - if methods != None and len(list(methods)) > 0: - f.write('\n### Member Functions \n') - for m in list(methods): - make_method(f, node.attrib['name'], m, False) - - events = node.find('signals') - if events != None and len(list(events)) > 0: - f.write('\n### Signals \n') - for m in list(events): - make_method(f, node.attrib['name'], m, True, True) - d = m.find('description') - if d == None or d.text.strip() == '': - continue - f.write('\n') - f.write(dokuize_text(d.text.strip())) - f.write('\n') - - members = node.find('members') - - if members != None and len(list(members)) > 0: - f.write('\n### Member Variables \n') - - for c in list(members): - s = ' * ' - s += make_type(c.attrib['type']) + ' ' - s += '**' + c.attrib['name'] + '**' - if c.text.strip() != '': - s += ' - ' + c.text.strip() - f.write(s + '\n') - - constants = node.find('constants') - if constants != None and len(list(constants)) > 0: - f.write('\n### Numeric Constants \n') - for c in list(constants): - s = ' * ' - s += '**' + c.attrib['name'] + '**' - if 'value' in c.attrib: - s += ' = **' + c.attrib['value'] + '**' - if c.text.strip() != '': - s += ' - ' + c.text.strip() - f.write(s + '\n') - - descr = node.find('description') - if descr != None and descr.text.strip() != '': - f.write('\n### Description \n') - f.write(dokuize_text(descr.text.strip()) + '\n') - - methods = node.find('methods') - - if methods != None and len(list(methods)) > 0: - f.write('\n### Member Function Description \n') - for m in list(methods): - - d = m.find('description') - if d == None or d.text.strip() == '': - continue - f.write('\n#### <a name="' + m.attrib['name'] + '">' + m.attrib['name'] + '</a>\n') - make_method(f, node.attrib['name'], m, True) - f.write('\n') - f.write(dokuize_text(d.text.strip())) - f.write('\n') - - f.close() - - -for file in input_list: - tree = ET.parse(file) - doc = tree.getroot() - - if 'version' not in doc.attrib: - print "Version missing from 'doc'" - sys.exit(255) - - version = doc.attrib['version'] - class_name = doc.attrib['name'] - if class_name in class_names: - continue - class_names.append(class_name) - classes[class_name] = doc - -class_names.sort() - -make_class_list(class_names, 2) - -for cn in class_names: - c = classes[cn] - make_doku_class(c) diff --git a/editor/icons/icon_GUI_viewport_hdiagsplitter.svg b/editor/icons/icon_GUI_viewport_hdiagsplitter.svg new file mode 100644 index 0000000000..36769768fd --- /dev/null +++ b/editor/icons/icon_GUI_viewport_hdiagsplitter.svg @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64" + height="34" + version="1.1" + viewBox="0 0 64 34" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter1.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="5.6568543" + inkscape:cx="37.006499" + inkscape:cy="15.680715" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-1018.4)" + id="g4" /> + <g + transform="rotate(90,541.2,539.2)" + id="g4-3"> + <path + id="path2-6" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + d="M 4.0306826,1048.4 H 34 m -30,30 v -60" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + </g> +</svg> diff --git a/editor/icons/icon_GUI_viewport_vdiagsplitter.svg b/editor/icons/icon_GUI_viewport_vdiagsplitter.svg new file mode 100644 index 0000000000..f23b4a0a74 --- /dev/null +++ b/editor/icons/icon_GUI_viewport_vdiagsplitter.svg @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="34" + height="64" + version="1.1" + viewBox="0 0 34 64" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter2.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="4" + inkscape:cx="32.245723" + inkscape:cy="44.255214" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-988.4)" + id="g4" /> + <g + id="g839" + transform="rotate(90,32.003536,32.003535)"> + <g + id="g4-3" + transform="rotate(90,526.2,554.2)"> + <path + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + d="M 4.0306826,1048.4 H 34 m -30,30 v -60" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + id="path2-6" /> + </g> + </g> +</svg> diff --git a/editor/icons/icon_GUI_viewport_vhsplitter.svg b/editor/icons/icon_GUI_viewport_vhsplitter.svg new file mode 100644 index 0000000000..429cf909ae --- /dev/null +++ b/editor/icons/icon_GUI_viewport_vhsplitter.svg @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64" + height="64" + version="1.1" + viewBox="0 0 64 64" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="4.65625" + inkscape:cx="9.8488117" + inkscape:cy="20.04653" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-988.4)" + id="g4" /> + <g + transform="rotate(90,526.2,554.2)" + id="g4-3"> + <path + id="path2-6" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + d="m -26,1048.4 h 60 m -30,30 v -60" + inkscape:connector-curvature="0" /> + </g> +</svg> diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index b68ea71cd4..114610c562 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -3543,69 +3543,77 @@ void SpatialEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { - Vector2 size = get_size(); + if (mb->is_pressed()) { + Vector2 size = get_size(); - int h_sep = get_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); - int mid_w = size.width * ratio_h; - int mid_h = size.height * ratio_v; + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; - dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); - dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); + dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); + dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); - drag_begin_pos = mb->get_position(); - drag_begin_ratio.x = ratio_h; - drag_begin_ratio.y = ratio_v; + drag_begin_pos = mb->get_position(); + drag_begin_ratio.x = ratio_h; + drag_begin_ratio.y = ratio_v; - switch (view) { - case VIEW_USE_1_VIEWPORT: { + switch (view) { + case VIEW_USE_1_VIEWPORT: { - dragging_h = false; - dragging_v = false; - - } break; - case VIEW_USE_2_VIEWPORTS: { - - dragging_h = false; + dragging_h = false; + dragging_v = false; - } break; - case VIEW_USE_2_VIEWPORTS_ALT: { + } break; + case VIEW_USE_2_VIEWPORTS: { - dragging_v = false; + dragging_h = false; - } break; - case VIEW_USE_3_VIEWPORTS: { + } break; + case VIEW_USE_2_VIEWPORTS_ALT: { - if (dragging_v) - dragging_h = false; - else dragging_v = false; - } break; - case VIEW_USE_3_VIEWPORTS_ALT: { + } break; + case VIEW_USE_3_VIEWPORTS: + case VIEW_USE_3_VIEWPORTS_ALT: + case VIEW_USE_4_VIEWPORTS: { - if (dragging_h) - dragging_v = false; - else - dragging_h = false; - } break; - case VIEW_USE_4_VIEWPORTS: { + // Do nothing. - } break; + } break; + } + } else { + dragging_h = false; + dragging_v = false; } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - dragging_h = false; - dragging_v = false; - } - Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && (dragging_h || dragging_v)) { + if (mm.is_valid()) { + + if (view == VIEW_USE_3_VIEWPORTS || view == VIEW_USE_3_VIEWPORTS_ALT || view == VIEW_USE_4_VIEWPORTS) { + Vector2 size = get_size(); + + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); + + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; + + bool was_hovering_h = hovering_h; + bool was_hovering_v = hovering_v; + hovering_h = mm->get_position().x > (mid_w - h_sep / 2) && mm->get_position().x < (mid_w + h_sep / 2); + hovering_v = mm->get_position().y > (mid_h - v_sep / 2) && mm->get_position().y < (mid_h + v_sep / 2); + + if (was_hovering_h != hovering_h || was_hovering_v != hovering_v) { + update(); + } + } if (dragging_h) { float new_ratio = drag_begin_ratio.x + (mm->get_position().x - drag_begin_pos.x) / get_size().width; @@ -3635,9 +3643,12 @@ void SpatialEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW && mouseover) { Ref<Texture> h_grabber = get_icon("grabber", "HSplitContainer"); - Ref<Texture> v_grabber = get_icon("grabber", "VSplitContainer"); + Ref<Texture> hdiag_grabber = get_icon("GuiViewportHdiagsplitter", "EditorIcons"); + Ref<Texture> vdiag_grabber = get_icon("GuiViewportVdiagsplitter", "EditorIcons"); + Ref<Texture> vh_grabber = get_icon("GuiViewportVhsplitter", "EditorIcons"); + Vector2 size = get_size(); int h_sep = get_constant("separation", "HSplitContainer"); @@ -3654,35 +3665,62 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { - //nothing to show + // Nothing to show. } break; case VIEW_USE_2_VIEWPORTS: { draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); } break; case VIEW_USE_2_VIEWPORTS_ALT: { draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); } break; case VIEW_USE_3_VIEWPORTS: { - draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(hdiag_grabber, Vector2(mid_w - hdiag_grabber->get_width() / 2, mid_h - v_grabber->get_height() / 4)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; case VIEW_USE_3_VIEWPORTS_ALT: { - draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vdiag_grabber, Vector2(mid_w - vdiag_grabber->get_width() + v_grabber->get_height() / 4, mid_h - vdiag_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } + } break; case VIEW_USE_4_VIEWPORTS: { Vector2 half(mid_w, mid_h); - draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); - draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vh_grabber, half - vh_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; } @@ -3726,6 +3764,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { + viewports[0]->show(); for (int i = 1; i < 4; i++) { viewports[i]->hide(); @@ -3736,7 +3775,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3750,7 +3789,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3763,7 +3802,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3778,7 +3817,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3793,7 +3832,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_4_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { viewports[i]->show(); } @@ -3826,10 +3865,13 @@ void SpatialEditorViewportContainer::_bind_methods() { SpatialEditorViewportContainer::SpatialEditorViewportContainer() { + set_clip_contents(true); view = VIEW_USE_1_VIEWPORT; mouseover = false; ratio_h = 0.5; ratio_v = 0.5; + hovering_v = false; + hovering_h = false; dragging_v = false; dragging_h = false; } diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 773739d6e0..c552f21e39 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -404,6 +404,7 @@ public: AcceptDialog *p_accept); Viewport *get_viewport_node() { return viewport; } + Camera *get_camera() { return camera; } // return the default camera object. SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index); }; @@ -443,6 +444,9 @@ private: float ratio_h; float ratio_v; + bool hovering_v; + bool hovering_h; + bool dragging_v; bool dragging_h; Vector2 drag_begin_pos; @@ -707,7 +711,6 @@ public: void register_gizmo_plugin(Ref<EditorSpatialGizmoPlugin> ref); - Camera *get_camera() { return NULL; } void edit(Spatial *p_spatial); void clear(); diff --git a/main/tests/test_astar.cpp b/main/tests/test_astar.cpp new file mode 100644 index 0000000000..8b48f075bc --- /dev/null +++ b/main/tests/test_astar.cpp @@ -0,0 +1,117 @@ +/*************************************************************************/ +/* test_astar.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "test_astar.h" + +#include "core/math/a_star.h" +#include "core/os/os.h" + +#include <stdio.h> + +namespace TestAStar { + +class ABCX : public AStar { +public: + enum { A, + B, + C, + X }; + + ABCX() { + add_point(A, Vector3(0, 0, 0)); + add_point(B, Vector3(1, 0, 0)); + add_point(C, Vector3(0, 1, 0)); + add_point(X, Vector3(0, 0, 1)); + connect_points(A, B); + connect_points(A, C); + connect_points(B, C); + connect_points(X, A); + } + + // Disable heuristic completely + float _compute_cost(int p_from, int p_to) { + if (p_from == A && p_to == C) { + return 1000; + } + return 100; + } +}; + +bool test_abc() { + ABCX abcx; + PoolVector<int> path = abcx.get_id_path(ABCX::A, ABCX::C); + bool ok = path.size() == 3; + int i = 0; + ok = ok && path[i++] == ABCX::A; + ok = ok && path[i++] == ABCX::B; + ok = ok && path[i++] == ABCX::C; + return ok; +} + +bool test_abcx() { + ABCX abcx; + PoolVector<int> path = abcx.get_id_path(ABCX::X, ABCX::C); + bool ok = path.size() == 4; + int i = 0; + ok = ok && path[i++] == ABCX::X; + ok = ok && path[i++] == ABCX::A; + ok = ok && path[i++] == ABCX::B; + ok = ok && path[i++] == ABCX::C; + return ok; +} + +typedef bool (*TestFunc)(void); + +TestFunc test_funcs[] = { + test_abc, + test_abcx, + NULL +}; + +MainLoop *test() { + int count = 0; + int passed = 0; + + while (true) { + if (!test_funcs[count]) + break; + bool pass = test_funcs[count](); + if (pass) + passed++; + OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED"); + + count++; + } + OS::get_singleton()->print("\n"); + OS::get_singleton()->print("Passed %i of %i tests\n", passed, count); + return NULL; +} + +} // namespace TestAStar diff --git a/main/tests/test_astar.h b/main/tests/test_astar.h new file mode 100644 index 0000000000..6458f9efb1 --- /dev/null +++ b/main/tests/test_astar.h @@ -0,0 +1,41 @@ +/*************************************************************************/ +/* test_astar.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 TEST_ASTAR_H +#define TEST_ASTAR_H + +#include "core/os/main_loop.h" + +namespace TestAStar { + +MainLoop *test(); +} + +#endif diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index cd70b95a28..714a254371 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -33,6 +33,7 @@ #ifdef DEBUG_ENABLED +#include "test_astar.h" #include "test_gdscript.h" #include "test_gui.h" #include "test_image.h" @@ -64,6 +65,7 @@ const char **tests_get_names() { "gd_bytecode", "image", "ordered_hash_map", + "astar", NULL }; @@ -149,6 +151,11 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestOrderedHashMap::test(); } + if (p_test == "astar") { + + return TestAStar::test(); + } + return NULL; } diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 2221923093..f766c0722d 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -217,6 +217,16 @@ void SpinBox::_notification(int p_what) { } } +void SpinBox::set_align(LineEdit::Align p_align) { + + line_edit->set_align(p_align); +} + +LineEdit::Align SpinBox::get_align() const { + + return line_edit->get_align(); +} + void SpinBox::set_suffix(const String &p_suffix) { suffix = p_suffix; @@ -253,6 +263,8 @@ void SpinBox::_bind_methods() { //ClassDB::bind_method(D_METHOD("_value_changed"),&SpinBox::_value_changed); ClassDB::bind_method(D_METHOD("_gui_input"), &SpinBox::_gui_input); ClassDB::bind_method(D_METHOD("_text_entered"), &SpinBox::_text_entered); + ClassDB::bind_method(D_METHOD("set_align", "align"), &SpinBox::set_align); + ClassDB::bind_method(D_METHOD("get_align"), &SpinBox::get_align); ClassDB::bind_method(D_METHOD("set_suffix", "suffix"), &SpinBox::set_suffix); ClassDB::bind_method(D_METHOD("get_suffix"), &SpinBox::get_suffix); ClassDB::bind_method(D_METHOD("set_prefix", "prefix"), &SpinBox::set_prefix); @@ -264,6 +276,7 @@ void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("_line_edit_input"), &SpinBox::_line_edit_input); ClassDB::bind_method(D_METHOD("_range_click_timeout"), &SpinBox::_range_click_timeout); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 8863f44bef..f1ee26d9f3 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -76,6 +76,9 @@ public: virtual Size2 get_minimum_size() const; + void set_align(LineEdit::Align p_align); + LineEdit::Align get_align() const; + void set_editable(bool p_editable); bool is_editable() const; |