int ItemList::get_item_at_pos(const Point2& p_pos) const { Vector2 pos=p_pos; Ref<StyleBox> bg = get_stylebox("bg"); pos-=bg->get_offset(); pos.y+=scroll_bar->get_val(); int closest = -1; int closest_dist=0x7FFFFFFF; for(int i=0;i<items.size();i++) { Rect2 rc = items[i].rect_cache; if (i%current_columns==current_columns-1) { rc.size.width=get_size().width; //not right but works } if (rc.has_point(pos)) { closest=i; break; } float dist = rc.distance_to(pos); if (dist<closest_dist) { closest=i; closest_dist=dist; } } return closest; }
bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos) { if (!Rect2(pos.x - port_grab_distance_horizontal, pos.y - port_grab_distance_vertical, port_grab_distance_horizontal * 2, port_grab_distance_vertical * 2).has_point(p_mouse_pos)) return false; for (int i = 0; i < get_child_count(); i++) { Control *child = Object::cast_to<Control>(get_child(i)); if (!child) continue; Rect2 rect = child->get_rect(); if (rect.has_point(p_mouse_pos)) { //check sub-controls Vector2 subpos = p_mouse_pos - rect.position; for (int j = 0; j < child->get_child_count(); j++) { Control *subchild = Object::cast_to<Control>(child->get_child(j)); if (!subchild) continue; if (_check_clickable_control(subchild, subpos - subchild->get_position())) { return false; } } } } return true; }
void Particles2DEditorPlugin::_generate_visibility_rect() { float time = generate_seconds->get_value(); float running = 0.0; EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); Rect2 rect; while (running < time) { uint64_t ticks = OS::get_singleton()->get_ticks_usec(); ep.step("Generating..", int(running), true); OS::get_singleton()->delay_usec(1000); Rect2 capture = particles->capture_rect(); if (rect == Rect2()) rect = capture; else rect = rect.merge(capture); running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0; } particles->set_visibility_rect(rect); }
void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) { static const int steps = 20; Rect2 r; r.pos=p_from; r.expand_to(p_to); Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1); bool flip = sign.x * sign.y < 0; Vector2 prev; for(int i=0;i<=steps;i++) { float d = i/float(steps); float c=-Math::cos(d*Math_PI) * 0.5+0.5; if (flip) c=1.0-c; Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height); if (i>0) { top_layer->draw_line(prev,p,p_color,2); } prev=p; } }
void TileMapEditor::_update_palette() { if (!node) return; int selected = get_selected_tile(); palette->clear(); Ref<TileSet> tileset=node->get_tileset(); if (tileset.is_null()) return; List<int> tiles; tileset->get_tile_list(&tiles); if (tiles.empty()) return; palette->set_max_columns(0); palette->set_icon_mode(ItemList::ICON_MODE_TOP); palette->set_max_text_lines(2); String filter = search_box->get_text().strip_edges(); for (List<int>::Element *E=tiles.front();E;E=E->next()) { String name; if (tileset->tile_get_name(E->get())!="") { name = tileset->tile_get_name(E->get()); } else { name = "#"+itos(E->get()); } if (filter != "" && name.findn(filter) == -1) continue; palette->add_item(name); Ref<Texture> tex = tileset->tile_get_texture(E->get()); if (tex.is_valid()) { Rect2 region = tileset->tile_get_region(E->get()); if (!region.has_no_area()) palette->set_item_icon_region(palette->get_item_count()-1, region); palette->set_item_icon(palette->get_item_count()-1, tex); } palette->set_item_metadata(palette->get_item_count()-1, E->get()); } if (selected != -1) set_selected_tile(selected); else palette->select(0, true); }
bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); _RestCallbackData rcd; rcd.best_len=0; rcd.best_object=NULL; rcd.best_shape=0; for(int i=0;i<amount;i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (p_exclude.has( col_obj->get_self() )) continue; rcd.object=col_obj; rcd.shape=shape_idx; bool sc = CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_rest_cbk_result,&rcd,NULL,p_margin); if (!sc) continue; } if (rcd.best_len==0) return false; r_info->collider_id=rcd.best_object->get_instance_id(); r_info->shape=rcd.best_shape; r_info->normal=rcd.best_normal; r_info->point=rcd.best_contact; r_info->rid=rcd.best_object->get_self(); if (rcd.best_object->get_type()==CollisionObject2DSW::TYPE_BODY) { const Body2DSW *body = static_cast<const Body2DSW*>(rcd.best_object); Vector2 rel_vec = r_info->point-body->get_transform().get_origin(); r_info->linear_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); } else { r_info->linear_velocity=Vector2(); } return true; }
void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY); if (points) memdelete_arr(points); points=NULL; point_count=0; if (p_data.get_type()==Variant::VECTOR2_ARRAY) { DVector<Vector2> arr=p_data; ERR_FAIL_COND(arr.size()==0); point_count=arr.size(); points = memnew_arr(Point,point_count); DVector<Vector2>::Read r = arr.read(); for(int i=0;i<point_count;i++) { points[i].pos=r[i]; } for(int i=0;i<point_count;i++) { Vector2 p = points[i].pos; Vector2 pn = points[(i+1)%point_count].pos; points[i].normal=(pn-p).tangent().normalized(); } } else { DVector<real_t> dvr = p_data; point_count=dvr.size()/4; ERR_FAIL_COND(point_count==0); points = memnew_arr(Point,point_count); DVector<real_t>::Read r = dvr.read(); for(int i=0;i<point_count;i++) { int idx=i<<2; points[i].pos.x=r[idx+0]; points[i].pos.y=r[idx+1]; points[i].normal.x=r[idx+2]; points[i].normal.y=r[idx+3]; } } ERR_FAIL_COND(point_count==0); Rect2 aabb; aabb.pos=points[0].pos; for(int i=1;i<point_count;i++) aabb.expand_to(points[i].pos); configure(aabb); }
void handleMouse(const Rect2& view, int viewportWidth, int viewportHeight) { int x, y; ubyte state = SDL_GetMouseState(&x, &y); real vx = x; real vy = viewportHeight-y; gMouseX = (vx/viewportWidth)*view.width()+view.left(); gMouseY = (vy/viewportHeight)*view.height()+view.bottom(); gMouseButton = state & SDL_BUTTON(1); }
real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass) const { Rect2 aabb; aabb.pos=points[0].pos; for(int i=0;i<point_count;i++) { aabb.expand_to(points[i].pos); } return p_mass*aabb.size.dot(aabb.size)/12.0f; }
bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); bool collided=false; int cc=0; r_result_count=0; Physics2DServerSW::CollCbkData cbk; cbk.max=p_result_max; cbk.amount=0; cbk.ptr=r_results; CollisionSolver2DSW::CallbackResult cbkres=NULL; Physics2DServerSW::CollCbkData *cbkptr=NULL; if (p_result_max>0) { cbkptr=&cbk; cbkres=Physics2DServerSW::_shape_col_cbk; } for(int i=0;i<amount;i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (p_exclude.has( col_obj->get_self() )) continue; if (CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),cbkres,cbkptr,NULL,p_margin)) { collided=true; } } r_result_count=cbk.amount; return collided; }
real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { Rect2 aabb; aabb.pos=points[0].pos*p_scale; for(int i=0;i<point_count;i++) { aabb.expand_to(points[i].pos*p_scale); } return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared(); }
Rect2 Line2D::_edit_get_rect() const { if (_points.size() == 0) return Rect2(0, 0, 0, 0); Vector2 d = Vector2(_width, _width); Rect2 aabb = Rect2(_points[0] - d, 2 * d); for (int i = 1; i < _points.size(); i++) { aabb.expand_to(_points[i] - d); aabb.expand_to(_points[i] + d); } return aabb; }
Rect2 ConvexPolygonShape2D::get_rect() const { Rect2 rect; for (int i = 0; i < points.size(); i++) { if (i == 0) rect.position = points[i]; else rect.expand_to(points[i]); } return rect; }
void TileMapEditor::_update_palette() { if (!node) return; palette->clear(); Ref<TileSet> tileset=node->get_tileset(); if (!tileset.is_valid()) return; List<int> tiles; tileset->get_tile_list(&tiles); if (display_mode == DISPLAY_THUMBNAIL) { palette->set_max_columns(0); palette->set_icon_mode(ItemList::ICON_MODE_TOP); } else if (display_mode == DISPLAY_LIST) { palette->set_max_columns(1); palette->set_icon_mode(ItemList::ICON_MODE_LEFT); } palette->set_max_text_lines(2); for(List<int>::Element *E=tiles.front();E;E=E->next()) { palette->add_item(""); Ref<Texture> tex = tileset->tile_get_texture(E->get()); if (tex.is_valid()) { Rect2 region = tileset->tile_get_region(E->get()); if (!region.has_no_area()) { Image data = VS::get_singleton()->texture_get_data(tex->get_rid()); Ref<ImageTexture> img = memnew( ImageTexture ); img->create_from_image(data.get_rect(region)); palette->set_item_icon(palette->get_item_count()-1, img); } else { palette->set_item_icon(palette->get_item_count()-1,tex); } } if (tileset->tile_get_name(E->get())!="") { palette->set_item_text(palette->get_item_count()-1, tileset->tile_get_name(E->get())); } else { palette->set_item_text(palette->get_item_count()-1, "#"+itos(E->get())); } palette->set_item_metadata(palette->get_item_count()-1, E->get()); } }
Rect2 LineShape2D::get_rect() const { Vector2 point = get_d() * get_normal(); Vector2 l1[2] = { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }; Vector2 l2[2] = { point, point + get_normal() * 30 }; Rect2 rect; rect.pos = l1[0]; rect.expand_to(l1[1]); rect.expand_to(l2[0]); rect.expand_to(l2[1]); return rect; }
void GraphEdit::_update_scroll() { if (updating) return; updating = true; set_block_minimum_size_adjust(true); Rect2 screen; for (int i = 0; i < get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); if (!gn) continue; Rect2 r; r.position = gn->get_offset() * zoom; r.size = gn->get_size() * zoom; screen = screen.merge(r); } screen.position -= get_size(); screen.size += get_size() * 2.0; h_scroll->set_min(screen.position.x); h_scroll->set_max(screen.position.x + screen.size.x); h_scroll->set_page(get_size().x); if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page()) h_scroll->hide(); else h_scroll->show(); v_scroll->set_min(screen.position.y); v_scroll->set_max(screen.position.y + screen.size.y); v_scroll->set_page(get_size().y); if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page()) v_scroll->hide(); else v_scroll->show(); set_block_minimum_size_adjust(false); if (!awaiting_scroll_offset_update) { call_deferred("_update_scroll_offset"); awaiting_scroll_offset_update = true; } updating = false; }
void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color) { #if 1 //cubic bezier code float diff = p_to.x - p_from.x; float cp_offset; int cp_len = get_constant("bezier_len_pos"); int cp_neg_len = get_constant("bezier_len_neg"); if (diff > 0) { cp_offset = MAX(cp_len, diff * 0.5); } else { cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5); } Vector2 c1 = Vector2(cp_offset * zoom, 0); Vector2 c2 = Vector2(-cp_offset * zoom, 0); int lines = 0; _bake_segment2d(p_where, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); #else static const int steps = 20; //old cosine code Rect2 r; r.pos = p_from; r.expand_to(p_to); Vector2 sign = Vector2((p_from.x < p_to.x) ? 1 : -1, (p_from.y < p_to.y) ? 1 : -1); bool flip = sign.x * sign.y < 0; Vector2 prev; for (int i = 0; i <= steps; i++) { float d = i / float(steps); float c = -Math::cos(d * Math_PI) * 0.5 + 0.5; if (flip) c = 1.0 - c; Vector2 p = r.pos + Vector2(d * r.size.width, c * r.size.height); if (i > 0) { p_where->draw_line(prev, p, p_color.linear_interpolate(p_to_color, d), 2); } prev = p; } #endif }
Rect2 CanvasItem::_edit_get_item_and_children_rect() const { Rect2 rect = _edit_get_rect(); for (int i = 0; i < get_child_count(); i++) { CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i)); if (c) { Rect2 sir = c->get_transform().xform(c->_edit_get_item_and_children_rect()); rect = rect.merge(sir); } } return rect; }
// mesh = m, dir = vector(1, 0, 0) void Intersector::init() { int i, j, k; const vector<MeshVertex> &vtc = mesh->vertices; const vector<MeshEdge> &edg = mesh->edges; dir = dir.normalize(); getBasis(dir, v1, v2); // 建立一个以dir, v1, v2为坐标轴的坐标系 // dir(1, 0, 0) v1(0, 0, 1) v2(0, -1, 0) points.resize(vtc.size()); sNormals.resize(edg.size() / 3); for(i = 0; i < (int)vtc.size(); ++i) { // *表示内积 points[i] = Vector2(vtc[i].pos * v1, vtc[i].pos * v2); } bounds = Rect2(points.begin(), points.end()); // points数组存储的是每个顶点在v1和v2方向上的投影,bounds是这些投影的二维包围盒 triangles.resize(cells * cells); for(i = 0; i < (int)edg.size(); i += 3) { Rect2 triRect; for(j = 0; j < 3; ++j) triRect |= Rect2(points[edg[i + j].vertex]); int fromx, fromy, tox, toy; getIndex(triRect.getLo(), fromx, fromy); getIndex(triRect.getHi(), tox, toy); // 得到的fromx, fromy分别是将bounds分为200*200的网格后,其包围盒左下角在整个网格(bounds)中的x,y方向上的网格索引号 // tox, toy是三角形包围盒右上角在网格中的索引号 for(j = fromy; j <= toy; ++j) for(k = fromx; k <= tox; ++k) { triangles[j * cells + k].push_back(i); } // triangles中存储的是与这些网格有交点的三角面片 Vector3 cross = (vtc[edg[i + 1].vertex].pos - vtc[edg[i].vertex].pos) % (vtc[edg[i + 2].vertex].pos - vtc[edg[i].vertex].pos); j = i / 3; // j为面片的索引号 sNormals[j] = cross.normalize(); if(fabs(sNormals[j] * dir) <= 1e-8) sNormals[j] = Vector3(); //zero if coplanar else sNormals[j] = sNormals[j] / (sNormals[j] * dir); //prescaled for intersection // sNormals[j]为平面的法向在dir方向上的投影 } }
int Tabs::get_tab_idx_at_point(const Point2 &p_point) const { int hover_now = -1; for (int i = 0; i < tabs.size(); i++) { if (i < offset) continue; Rect2 rect = get_tab_rect(i); if (rect.has_point(p_point)) { hover_now = i; } } return hover_now; }
void ControlEditor::_find_controls_span(Node *p_node, Rect2& r_rect) { if (!editor->get_scene()) return; if (p_node!=editor->get_edited_scene() && p_node->get_owner()!=editor->get_edited_scene()) return; if (p_node->cast_to<Control>()) { Control *c = p_node->cast_to<Control>(); if (c->get_viewport() != editor->get_viewport()->get_viewport()) return; //bye, it's in another viewport if (!c->get_parent_control()) { Rect2 span = c->get_subtree_span_rect(); r_rect.merge(span); } } for(int i=0;i<p_node->get_child_count();i++) { _find_controls_span(p_node->get_child(i),r_rect); } }
int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); Rect2 aabb = p_xform.xform(shape->get_aabb()); aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); bool collided=false; int cc=0; for(int i=0; i<amount; i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; if (p_exclude.has( space->intersection_query_results[i]->get_self())) continue; const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),NULL,NULL,NULL,p_margin)) continue; r_results[cc].collider_id=col_obj->get_instance_id(); if (r_results[cc].collider_id!=0) r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); r_results[cc].rid=col_obj->get_self(); r_results[cc].shape=shape_idx; r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx); cc++; } return cc; }
void SegmentShape2DSW::set_data(const Variant& p_data) { ERR_FAIL_COND(p_data.get_type()!=Variant::RECT2); Rect2 r = p_data; a=r.pos; b=r.size; n=(b-a).tangent(); Rect2 aabb; aabb.pos=a; aabb.expand_to(b); if (aabb.size.x==0) aabb.size.x=0.001; if (aabb.size.y==0) aabb.size.y=0.001; configure(aabb); }
Rect2 Path2D::_edit_get_rect() const { if (!curve.is_valid() || curve->get_point_count() == 0) return Rect2(0, 0, 0, 0); Rect2 aabb = Rect2(curve->get_point_position(0), Vector2(0, 0)); for (int i = 0; i < curve->get_point_count(); i++) { for (int j = 0; j <= 8; j++) { real_t frac = j / 8.0; Vector2 p = curve->interpolate(i, frac); aabb.expand_to(p); } } return aabb; }
Rect2 ConcavePolygonShape2D::get_rect() const { PoolVector<Vector2> s = get_segments(); int len = s.size(); if (len == 0) return Rect2(); Rect2 rect; PoolVector<Vector2>::Read r = s.read(); for (int i = 0; i < len; i++) { if (i == 0) rect.position = r[i]; else rect.expand_to(r[i]); } return rect; }
int BroadPhase2DBasic::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { int rc = 0; for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { const Rect2 aabb = E->get().aabb; if (aabb.intersects_segment(p_from, p_to)) { p_results[rc] = E->get().owner; p_result_indices[rc] = E->get().subindex; rc++; if (rc >= p_max_results) break; } } return rc; }
void GraphEdit::_update_scroll() { if (updating) return; updating=true; Rect2 screen; for(int i=0;i<get_child_count();i++) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); if (!gn) continue; Rect2 r; r.pos=gn->get_offset(); r.size=gn->get_size(); screen = screen.merge(r); } screen.pos-=get_size(); screen.size+=get_size()*2.0; h_scroll->set_min(screen.pos.x); h_scroll->set_max(screen.pos.x+screen.size.x); h_scroll->set_page(get_size().x); if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page()) h_scroll->hide(); else h_scroll->show(); v_scroll->set_min(screen.pos.y); v_scroll->set_max(screen.pos.y+screen.size.y); v_scroll->set_page(get_size().y); if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page()) v_scroll->hide(); else v_scroll->show(); _update_scroll_offset(); updating=false; }
DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start) { if (node->get_cell(p_start.x, p_start.y) != TileMap::INVALID_CELL) return DVector<Vector2>(); int id = get_selected_tile(); if (id == TileMap::INVALID_CELL) return DVector<Vector2>(); Rect2 r = node->get_item_rect(); r.pos = r.pos/node->get_cell_size(); r.size = r.size/node->get_cell_size(); DVector<Vector2> points; List<Point2i> queue; queue.push_back(p_start); while (queue.size()) { Point2i n = queue.front()->get(); queue.pop_front(); if (!r.has_point(n)) continue; if (node->get_cell(n.x, n.y) == TileMap::INVALID_CELL) { node->set_cellv(n, id, flip_h, flip_v, transpose); points.push_back(n); queue.push_back(n + Point2i(0, 1)); queue.push_back(n + Point2i(0, -1)); queue.push_back(n + Point2i(1, 0)); queue.push_back(n + Point2i(-1, 0)); } } return points; }
void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(Vector2 &r_from, Vector2 &r_to, const Rect2 &p_rect) { if (r_to == r_from) return; //this could be optimized... Vector2 n = (r_to - r_from).normalized(); while (p_rect.has_point(r_to)) { r_to -= n; } }
// slow as hell Control* ControlEditor::_select_control_at_pos(const Point2& p_pos,Node* p_node) { for (int i=p_node->get_child_count()-1;i>=0;i--) { Control *r=_select_control_at_pos(p_pos,p_node->get_child(i)); if (r) return r; } Control *c=p_node->cast_to<Control>(); if (c) { Rect2 rect = c->get_window_rect(); if (c->get_window()==current_window) { rect.pos=transform.xform(rect.pos).floor(); } if (rect.has_point(p_pos)) return c; } return NULL; }