Esempio n. 1
0
	void _ray_query_callback(const RID &p_rid, ObjectID p_id, int p_shape, const Vector2 &p_point, const Vector2 &p_normal) {

		Vector2 ray_end;

		if (p_rid.is_valid()) {
			ray_end = p_point;
		} else {
			ray_end = ray_to;
		}

		VisualServer *vs = VisualServer::get_singleton();

		vs->canvas_item_clear(ray);
		vs->canvas_item_add_line(ray, ray_from, ray_end, p_rid.is_valid() ? Color(0, 1, 0.4) : Color(1, 0.4, 0), 2);
		if (p_rid.is_valid())
			vs->canvas_item_add_line(ray, ray_end, ray_end + p_normal * 20, p_rid.is_valid() ? Color(0, 1, 0.4) : Color(1, 0.4, 0), 2);
	}
Esempio n. 2
0
	void _add_concave(const Vector<Vector2> &p_points, const Matrix32 &p_xform = Matrix32()) {

		Physics2DServer *ps = Physics2DServer::get_singleton();
		VisualServer *vs = VisualServer::get_singleton();

		RID concave = ps->shape_create(Physics2DServer::SHAPE_CONCAVE_POLYGON);
		ps->shape_set_data(concave, p_points);
		RID body = ps->body_create(Physics2DServer::BODY_MODE_STATIC);
		ps->body_set_space(body, space);
		ps->body_add_shape(body, concave);
		ps->body_set_state(body, Physics2DServer::BODY_STATE_TRANSFORM, p_xform);

		RID sprite = vs->canvas_item_create();
		vs->canvas_item_set_parent(sprite, canvas);
		vs->canvas_item_set_transform(sprite, p_xform);
		for (int i = 0; i < p_points.size(); i += 2) {
			vs->canvas_item_add_line(sprite, p_points[i], p_points[i + 1], Color(0, 0, 0), 2);
		}
	}
Esempio n. 3
0
void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {

	VisualServer *vs = VisualServer::get_singleton();
	Rect2i r = p_rect;

	for (int i = 0; i < border_size; i++) {

		Color color_upleft = light_color;
		Color color_downright = dark_color;

		if (blend) {

			color_upleft.r = (border_size - i) * color_upleft.r / border_size + i * bg_color.r / border_size;
			color_upleft.g = (border_size - i) * color_upleft.g / border_size + i * bg_color.g / border_size;
			color_upleft.b = (border_size - i) * color_upleft.b / border_size + i * bg_color.b / border_size;

			color_downright.r = (border_size - i) * color_downright.r / border_size + i * bg_color.r / border_size;
			color_downright.g = (border_size - i) * color_downright.g / border_size + i * bg_color.g / border_size;
			color_downright.b = (border_size - i) * color_downright.b / border_size + i * bg_color.b / border_size;
		}

		vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r.position.x, r.position.y + r.size.y - 1), Size2(r.size.x, 1)), color_downright);
		vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r.position.x + r.size.x - 1, r.position.y), Size2(1, r.size.y)), color_downright);

		vs->canvas_item_add_rect(p_canvas_item, Rect2(r.position, Size2(r.size.x, 1)), color_upleft);
		vs->canvas_item_add_rect(p_canvas_item, Rect2(r.position, Size2(1, r.size.y)), color_upleft);

		r.position.x++;
		r.position.y++;
		r.size.x -= 2;
		r.size.y -= 2;
	}

	if (draw_center)
		vs->canvas_item_add_rect(p_canvas_item, Rect2(r.position, r.size), bg_color);

	Rect2i r_add = p_rect;
	vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r_add.position.x - additional_border_size[MARGIN_LEFT], r_add.position.y - additional_border_size[MARGIN_TOP]), Size2(r_add.size.width + additional_border_size[MARGIN_LEFT] + additional_border_size[MARGIN_RIGHT], additional_border_size[MARGIN_TOP])), light_color);
	vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r_add.position.x - additional_border_size[MARGIN_LEFT], r_add.position.y), Size2(additional_border_size[MARGIN_LEFT], r_add.size.height)), light_color);
	vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r_add.position.x + r_add.size.width, r_add.position.y), Size2(additional_border_size[MARGIN_RIGHT], r_add.size.height)), dark_color);
	vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r_add.position.x - additional_border_size[MARGIN_LEFT], r_add.position.y + r_add.size.height), Size2(r_add.size.width + additional_border_size[MARGIN_LEFT] + additional_border_size[MARGIN_RIGHT], additional_border_size[MARGIN_BOTTOM])), dark_color);
}
Esempio n. 4
0
void StyleBoxFlat::draw(RID p_canvas_item,const Rect2& p_rect) const {

	VisualServer *vs = VisualServer::get_singleton();
	Rect2i r = p_rect;

	for (int i=0;i<border_size;i++) {



		Color color_upleft=light_color;
		Color color_downright=dark_color;

		if (blend) {

			color_upleft.r=(border_size-i)*color_upleft.r/border_size + i*bg_color.r/border_size;
			color_upleft.g=(border_size-i)*color_upleft.g/border_size + i*bg_color.g/border_size;
			color_upleft.b=(border_size-i)*color_upleft.b/border_size + i*bg_color.b/border_size;

			color_downright.r=(border_size-i)*color_downright.r/border_size + i*bg_color.r/border_size;
			color_downright.g=(border_size-i)*color_downright.g/border_size + i*bg_color.g/border_size;
			color_downright.b=(border_size-i)*color_downright.b/border_size + i*bg_color.b/border_size;

		}

		vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i( r.pos.x,r.pos.y+r.size.y-1), Size2(r.size.x ,1 )),color_downright);
		vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i( r.pos.x+r.size.x-1,r.pos.y ), Size2( 1 ,r.size.y )), color_downright);

		vs->canvas_item_add_rect(p_canvas_item, Rect2( r.pos, Size2(r.size.x ,1 )), color_upleft);
		vs->canvas_item_add_rect(p_canvas_item, Rect2( r.pos, Size2( 1 ,r.size.y )), color_upleft);


		r.pos.x++;
		r.pos.y++;
		r.size.x-=2;
		r.size.y-=2;
	}

	if (draw_center)
		vs->canvas_item_add_rect(p_canvas_item, Rect2( r.pos, r.size) , bg_color );


}
Esempio n. 5
0
	RID _add_body(Physics2DServer::ShapeType p_shape, const Matrix32& p_xform) {

		VisualServer *vs = VisualServer::get_singleton();
		Physics2DServer *ps = Physics2DServer::get_singleton();

		RID body = ps->body_create();
		ps->body_add_shape(body,body_shape_data[p_shape].shape);
		ps->body_set_space(body,space);
		ps->body_set_continuous_collision_detection_mode(body,Physics2DServer::CCD_MODE_CAST_SHAPE);
		ps->body_set_state(body,Physics2DServer::BODY_STATE_TRANSFORM,p_xform);

//		print_line("add body with xform: "+p_xform);
		RID sprite = vs->canvas_item_create();
		vs->canvas_item_set_parent(sprite,canvas);
		vs->canvas_item_set_transform(sprite,p_xform);
		Size2 imgsize( vs->texture_get_width(body_shape_data[p_shape].image),vs->texture_get_height(body_shape_data[p_shape].image) );
		vs->canvas_item_add_texture_rect(sprite,Rect2(-imgsize/2.0,imgsize),body_shape_data[p_shape].image);

		ps->body_set_force_integration_callback(body,this,"_body_moved",sprite);
//		RID q = ps->query_create(this,"_body_moved",sprite);
//		ps->query_body_state(q,body);

		return body;
	}
Esempio n. 6
0
	void _create_body_shape_data() {
		VisualServer *vs = VisualServer::get_singleton();
		Physics2DServer *ps = Physics2DServer::get_singleton();

		// SEGMENT

		{

			DVector<uint8_t> pixels;
			pixels.resize(32*2*2);
			for(int i=0;i<2;i++) {

				for(int j=0;j<32;j++) {

					pixels.set(i*32*2+j*2+0,(j==0)?255:0);
					pixels.set(i*32*2+j*2+1,255);
				}
			}

			Image image(32,2,0,Image::FORMAT_LA8,pixels);

			body_shape_data[Physics2DServer::SHAPE_SEGMENT].image=vs->texture_create_from_image(image);

			RID segment_shape = ps->shape_create(Physics2DServer::SHAPE_SEGMENT);
			Rect2 sg(Point2(-16,0),Point2(16,0));
			ps->shape_set_data(segment_shape,sg);

			body_shape_data[Physics2DServer::SHAPE_SEGMENT].shape = segment_shape;

		}
		// CIRCLE

		{

			DVector<uint8_t> pixels;
			pixels.resize(32*32*2);
			for(int i=0;i<32;i++) {

				for(int j=0;j<32;j++) {

					bool black=Vector2(i-16,j-16).length_squared() < 16*16;

					pixels.set(i*32*2+j*2+0,(i==16 || j==16)?255:0);
					pixels.set(i*32*2+j*2+1,black?255:0);
				}
			}

			Image image(32,32,0,Image::FORMAT_LA8,pixels);

			body_shape_data[Physics2DServer::SHAPE_CIRCLE].image=vs->texture_create_from_image(image);

			RID circle_shape = ps->shape_create(Physics2DServer::SHAPE_CIRCLE);
			ps->shape_set_data(circle_shape,16);

			body_shape_data[Physics2DServer::SHAPE_CIRCLE].shape = circle_shape;

		}

		// BOX

		{

			DVector<uint8_t> pixels;
			pixels.resize(32*32*2);
			for(int i=0;i<32;i++) {

				for(int j=0;j<32;j++) {

					bool black=i>0 && i<31 && j>0 && j<31;

					pixels.set(i*32*2+j*2+0,black?0:255);
					pixels.set(i*32*2+j*2+1,255);
				}
			}

			Image image(32,32,0,Image::FORMAT_LA8,pixels);

			body_shape_data[Physics2DServer::SHAPE_RECTANGLE].image=vs->texture_create_from_image(image);

			RID rectangle_shape = ps->shape_create(Physics2DServer::SHAPE_RECTANGLE);
			ps->shape_set_data(rectangle_shape,Vector2(16,16));

			body_shape_data[Physics2DServer::SHAPE_RECTANGLE].shape = rectangle_shape;

		}


		// CAPSULE

		{

			DVector<uint8_t> pixels;
			pixels.resize(32*64*2);
			for(int i=0;i<64;i++) {

				for(int j=0;j<32;j++) {


					int si = i>48 ? i - 32 : (i<16 ? i : 16);
					bool black=Vector2(si-16,j-16).length_squared() < 16*16;

					pixels.set(i*32*2+j*2+0,(i==16 || j==16 || i==48)?255:0);
					pixels.set(i*32*2+j*2+1,black?255:0);

				}
			}

			Image image(32,64,0,Image::FORMAT_LA8,pixels);

			body_shape_data[Physics2DServer::SHAPE_CAPSULE].image=vs->texture_create_from_image(image);

			RID capsule_shape = ps->shape_create(Physics2DServer::SHAPE_CAPSULE);
			ps->shape_set_data(capsule_shape,Vector2(16,32));

			body_shape_data[Physics2DServer::SHAPE_CAPSULE].shape = capsule_shape;

		}

		// CONVEX

		{


			Image image(convex_png);

			body_shape_data[Physics2DServer::SHAPE_CUSTOM+1].image=vs->texture_create_from_image(image);

			RID convex_polygon_shape = ps->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON);

			DVector<Vector2> arr;
			Point2 sb(32,32);
			arr.push_back(Point2(20,3)-sb);
			arr.push_back(Point2(58,23)-sb);
			arr.push_back(Point2(55,54)-sb);
			arr.push_back(Point2(27,60)-sb);
			arr.push_back(Point2(5,56)-sb);
			arr.push_back(Point2(4,20)-sb);
			arr.push_back(Point2(11,7)-sb);
			ps->shape_set_data(convex_polygon_shape,arr);

			body_shape_data[Physics2DServer::SHAPE_CUSTOM+1].shape = convex_polygon_shape;

		}


	}
Esempio n. 7
0
	virtual void init() {

		VisualServer *vs = VisualServer::get_singleton();
		Physics2DServer *ps = Physics2DServer::get_singleton();



		space=ps->space_create();
		ps->space_set_active(space,true);
		ps->set_active(true);
		ps->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,Vector2(0,1));
		ps->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,98);

		{

			RID vp = vs->viewport_create();
			canvas = vs->canvas_create();
			vs->viewport_attach_canvas(vp,canvas);
			vs->viewport_attach_to_screen(vp,Rect2(Vector2(),OS::get_singleton()->get_window_size()));
			Matrix32 smaller;
			//smaller.scale(Vector2(0.6,0.6));
			//smaller.elements[2]=Vector2(100,0);

			//view_xform = smaller;
			vs->viewport_set_canvas_transform(vp,canvas,view_xform);

		}

		ray = vs->canvas_item_create();
		vs->canvas_item_set_parent(ray,canvas);
		//ray_query = ps->query_create(this,"_ray_query_callback",Variant());
		//ps->query_intersection(ray_query,space);

		_create_body_shape_data();

		for(int i=0;i<32;i++) {

			Physics2DServer::ShapeType types[4]={
				Physics2DServer::SHAPE_CIRCLE,
				Physics2DServer::SHAPE_CAPSULE,
				Physics2DServer::SHAPE_RECTANGLE,
				Physics2DServer::SHAPE_CONVEX_POLYGON,

			};

			Physics2DServer::ShapeType type = types[i%4];
//			type=Physics2DServer::SHAPE_SEGMENT;
			_add_body(type,Matrix32(i*0.8,Point2(152+i*40,100-40*i)));
			//if (i==0)
			//	ps->body_set_mode(b,Physics2DServer::BODY_MODE_STATIC);
		}

		//RID b= _add_body(Physics2DServer::SHAPE_CIRCLE,Matrix32(0,Point2(101,140)));
		//ps->body_set_mode(b,Physics2DServer::BODY_MODE_STATIC);

		Point2 prev;

		Vector<Point2> parr;
		for(int i=0;i<30;i++) {

			Point2 p(i*60,Math::randf() * 70+340);
			if (i>0) {
				parr.push_back(prev);
				parr.push_back(p);
			}
			prev=p;
		}

		_add_concave(parr);
		//_add_plane(Vector2(0.0,-1).normalized(),-300);
		//_add_plane(Vector2(1,0).normalized(),50);
		//_add_plane(Vector2(-1,0).normalized(),-600);

	}
Esempio n. 8
0
void ScrollBar::_notification(int p_what) {

	if (p_what == NOTIFICATION_DRAW) {

		RID ci = get_canvas_item();

		Ref<Texture> decr = highlight == HIGHLIGHT_DECR ? get_icon("decrement_highlight") : get_icon("decrement");
		Ref<Texture> incr = highlight == HIGHLIGHT_INCR ? get_icon("increment_highlight") : get_icon("increment");
		Ref<StyleBox> bg = has_focus() ? get_stylebox("scroll_focus") : get_stylebox("scroll");

		Ref<StyleBox> grabber;
		if (drag.active)
			grabber = get_stylebox("grabber_pressed");
		else if (highlight == HIGHLIGHT_RANGE)
			grabber = get_stylebox("grabber_highlight");
		else
			grabber = get_stylebox("grabber");

		Point2 ofs;

		VisualServer *vs = VisualServer::get_singleton();

		vs->canvas_item_add_texture_rect(ci, Rect2(Point2(), decr->get_size()), decr->get_rid());

		if (orientation == HORIZONTAL)
			ofs.x += decr->get_width();
		else
			ofs.y += decr->get_height();

		Size2 area = get_size();

		if (orientation == HORIZONTAL)
			area.width -= incr->get_width() + decr->get_width();
		else
			area.height -= incr->get_height() + decr->get_height();

		bg->draw(ci, Rect2(ofs, area));

		if (orientation == HORIZONTAL)
			ofs.width += area.width;
		else
			ofs.height += area.height;

		vs->canvas_item_add_texture_rect(ci, Rect2(ofs, decr->get_size()), incr->get_rid());
		Rect2 grabber_rect;

		if (orientation == HORIZONTAL) {

			grabber_rect.size.width = get_grabber_size();
			grabber_rect.size.height = get_size().height;
			grabber_rect.position.y = 0;
			grabber_rect.position.x = get_grabber_offset() + decr->get_width() + bg->get_margin(MARGIN_LEFT);
		} else {

			grabber_rect.size.width = get_size().width;
			grabber_rect.size.height = get_grabber_size();
			grabber_rect.position.y = get_grabber_offset() + decr->get_height() + bg->get_margin(MARGIN_TOP);
			grabber_rect.position.x = 0;
		}

		grabber->draw(ci, grabber_rect);
	}

	if (p_what == NOTIFICATION_ENTER_TREE) {

		if (has_node(drag_slave_path)) {
			Node *n = get_node(drag_slave_path);
			drag_slave = n->cast_to<Control>();
		}

		if (drag_slave) {
			drag_slave->connect("gui_input", this, "_drag_slave_input");
			drag_slave->connect("tree_exited", this, "_drag_slave_exit", varray(), CONNECT_ONESHOT);
		}
	}
	if (p_what == NOTIFICATION_EXIT_TREE) {

		if (drag_slave) {
			drag_slave->disconnect("gui_input", this, "_drag_slave_input");
			drag_slave->disconnect("tree_exited", this, "_drag_slave_exit");
		}

		drag_slave = NULL;
	}

	if (p_what == NOTIFICATION_FIXED_PROCESS) {

		if (scrolling) {
			if (get_value() != target_scroll) {
				double target = target_scroll - get_value();
				double dist = sqrt(target * target);
				double vel = ((target / dist) * 500) * get_fixed_process_delta_time();

				if (vel >= dist) {
					set_value(target_scroll);
				} else {
					set_value(get_value() + vel);
				}
			} else {
				scrolling = false;
				set_fixed_process(false);
			}
		} else if (drag_slave_touching) {

			if (drag_slave_touching_deaccel) {

				Vector2 pos = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
				pos += drag_slave_speed * get_fixed_process_delta_time();

				bool turnoff = false;

				if (orientation == HORIZONTAL) {

					if (pos.x < 0) {
						pos.x = 0;
						turnoff = true;
					}

					if (pos.x > (get_max() - get_page())) {
						pos.x = get_max() - get_page();
						turnoff = true;
					}

					set_value(pos.x);

					float sgn_x = drag_slave_speed.x < 0 ? -1 : 1;
					float val_x = Math::abs(drag_slave_speed.x);
					val_x -= 1000 * get_fixed_process_delta_time();

					if (val_x < 0) {
						turnoff = true;
					}

					drag_slave_speed.x = sgn_x * val_x;

				} else {

					if (pos.y < 0) {
						pos.y = 0;
						turnoff = true;
					}

					if (pos.y > (get_max() - get_page())) {
						pos.y = get_max() - get_page();
						turnoff = true;
					}

					set_value(pos.y);

					float sgn_y = drag_slave_speed.y < 0 ? -1 : 1;
					float val_y = Math::abs(drag_slave_speed.y);
					val_y -= 1000 * get_fixed_process_delta_time();

					if (val_y < 0) {
						turnoff = true;
					}
					drag_slave_speed.y = sgn_y * val_y;
				}

				if (turnoff) {
					set_fixed_process(false);
					drag_slave_touching = false;
					drag_slave_touching_deaccel = false;
				}

			} else {

				if (time_since_motion == 0 || time_since_motion > 0.1) {

					Vector2 diff = drag_slave_accum - last_drag_slave_accum;
					last_drag_slave_accum = drag_slave_accum;
					drag_slave_speed = diff / get_fixed_process_delta_time();
				}

				time_since_motion += get_fixed_process_delta_time();
			}
		}
	}

	if (p_what == NOTIFICATION_MOUSE_EXIT) {

		highlight = HIGHLIGHT_NONE;
		update();
	}
}
Esempio n. 9
0
void TileMap::_update_dirty_quadrants() {

	if (!pending_update)
		return;
	if (!is_inside_scene())
		return;
	if (!tile_set.is_valid())
		return;

	VisualServer *vs = VisualServer::get_singleton();
	Physics2DServer *ps = Physics2DServer::get_singleton();

	while (dirty_quadrant_list.first()) {

		Quadrant &q = *dirty_quadrant_list.first()->self();

		vs->canvas_item_clear(q.canvas_item);
		ps->body_clear_shapes(q.static_body);

		for(int i=0;i<q.cells.size();i++) {

			Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] );
			Cell &c=E->get();
			//moment of truth
			if (!tile_set->has_tile(c.id))
				continue;
			Ref<Texture> tex = tile_set->tile_get_texture(c.id);
			Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);

			Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;

			if (!tex.is_valid())
				continue;


			Rect2 r = tile_set->tile_get_region(c.id);
			Size2 s = tex->get_size();

			if (r==Rect2())
				s = tex->get_size();
			else {
				s = r.size;
				r.pos.x+=fp_adjust;
				r.pos.y+=fp_adjust;
				r.size.x-=fp_adjust*2.0;
				r.size.y-=fp_adjust*2.0;
			}

			Rect2 rect;
			rect.pos=offset.floor();
			rect.size=s;

			rect.size.x+=fp_adjust;
			rect.size.y+=fp_adjust;

			if (c.flip_h)
				rect.size.x=-rect.size.x;
			if (c.flip_v)
				rect.size.y=-rect.size.y;


			rect.pos+=tile_ofs;
			if (r==Rect2()) {

				tex->draw_rect(q.canvas_item,rect);
			} else {

				tex->draw_rect_region(q.canvas_item,rect,r);
			}

			Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);


			for(int i=0;i<shapes.size();i++) {

				Ref<Shape2D> shape = shapes[i];
				if (shape.is_valid()) {

					Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
					Matrix32 xform;
					xform.set_origin(offset.floor()+shape_ofs);
					if (c.flip_h) {
						xform.elements[0]=-xform.elements[0];
						xform.elements[2].x+=s.x;
					}
					if (c.flip_v) {
						xform.elements[1]=-xform.elements[1];
						xform.elements[2].y+=s.y;
					}


					ps->body_add_shape(q.static_body,shape->get_rid(),xform);
				}
			}
		}

		dirty_quadrant_list.remove( dirty_quadrant_list.first() );
	}



	pending_update=false;

	_recompute_rect_cache();

}
Esempio n. 10
0
void TileMap::_update_dirty_quadrants() {

	if (!pending_update)
		return;
	if (!is_inside_tree())
		return;
	if (!tile_set.is_valid())
		return;

	VisualServer *vs = VisualServer::get_singleton();
	Physics2DServer *ps = Physics2DServer::get_singleton();
	Vector2 tofs = get_cell_draw_offset();
	Vector2 tcenter = cell_size/2;
	Matrix32 nav_rel;
	if (navigation)
		nav_rel = get_relative_transform_to_parent(navigation);

	Vector2 qofs;

	SceneTree *st=SceneTree::get_singleton();
	Color debug_collision_color;

	bool debug_shapes = st && st->is_debugging_collisions_hint();
	if (debug_shapes) {
		debug_collision_color=st->get_debug_collisions_color();
	}

	while (dirty_quadrant_list.first()) {

		Quadrant &q = *dirty_quadrant_list.first()->self();

		for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) {

			vs->free(E->get());
		}

		q.canvas_items.clear();

		ps->body_clear_shapes(q.body);
		int shape_idx=0;

		if (navigation) {
			for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) {

				navigation->navpoly_remove(E->get().id);
			}
			q.navpoly_ids.clear();
		}

		for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) {
			VS::get_singleton()->free(E->get().id);
		}
		q.occluder_instances.clear();
		Ref<CanvasItemMaterial> prev_material;
		RID prev_canvas_item;
		RID prev_debug_canvas_item;

		for(int i=0;i<q.cells.size();i++) {

			Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] );
			Cell &c=E->get();
			//moment of truth
			if (!tile_set->has_tile(c.id))
				continue;
			Ref<Texture> tex = tile_set->tile_get_texture(c.id);
			Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);

			Vector2 wofs = _map_to_world(E->key().x, E->key().y);
			Vector2 offset = wofs - q.pos + tofs;

			if (!tex.is_valid())
				continue;

			Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id);

			RID canvas_item;
			RID debug_canvas_item;

			if (prev_canvas_item==RID() || prev_material!=mat) {

				canvas_item=vs->canvas_item_create();
				if (mat.is_valid())
					vs->canvas_item_set_material(canvas_item,mat->get_rid());
				vs->canvas_item_set_parent( canvas_item, get_canvas_item() );
				Matrix32 xform;
				xform.set_origin( q.pos );
				vs->canvas_item_set_transform( canvas_item, xform );
				vs->canvas_item_set_light_mask(canvas_item,get_light_mask());
				vs->canvas_item_set_blend_mode(canvas_item,VS::MaterialBlendMode(get_blend_mode()));

				q.canvas_items.push_back(canvas_item);

				if (debug_shapes) {

					debug_canvas_item=vs->canvas_item_create();
					vs->canvas_item_set_parent( debug_canvas_item, canvas_item );
					vs->canvas_item_set_z_as_relative_to_parent(debug_canvas_item,false);
					vs->canvas_item_set_z(debug_canvas_item,VS::CANVAS_ITEM_Z_MAX-1);
					q.canvas_items.push_back(debug_canvas_item);
					prev_debug_canvas_item=debug_canvas_item;
				}

				prev_canvas_item=canvas_item;
				prev_material=mat;

			} else {
				canvas_item=prev_canvas_item;
				if (debug_shapes) {
					debug_canvas_item=prev_debug_canvas_item;
				}
			}



			Rect2 r = tile_set->tile_get_region(c.id);
			Size2 s = tex->get_size();

			if (r==Rect2())
				s = tex->get_size();
			else {
				s = r.size;
				r.pos.x+=fp_adjust;
				r.pos.y+=fp_adjust;
				r.size.x-=fp_adjust*2.0;
				r.size.y-=fp_adjust*2.0;
			}

			Rect2 rect;
			rect.pos=offset.floor();
			rect.size=s;

			if (rect.size.y > rect.size.x) {
				if ((c.flip_h && (c.flip_v || c.transpose)) || (c.flip_v && !c.transpose))
					tile_ofs.y += rect.size.y - rect.size.x;
			} else if (rect.size.y < rect.size.x) {
				if ((c.flip_v && (c.flip_h || c.transpose)) || (c.flip_h && !c.transpose))
					tile_ofs.x += rect.size.x - rect.size.y;
			}

		/*	rect.size.x+=fp_adjust;
			rect.size.y+=fp_adjust;*/

			if (c.transpose)
				SWAP(tile_ofs.x, tile_ofs.y);

			if (c.flip_h) {
				rect.size.x=-rect.size.x;
				tile_ofs.x=-tile_ofs.x;
			}
			if (c.flip_v) {
				rect.size.y=-rect.size.y;
				tile_ofs.y=-tile_ofs.y;
			}

			Vector2 center_ofs;

			if (tile_origin==TILE_ORIGIN_TOP_LEFT) {
				rect.pos+=tile_ofs;
				
			} else if (tile_origin==TILE_ORIGIN_BOTTOM_LEFT) {
								
				rect.pos+=tile_ofs;
				
				if(c.transpose)
				{
					if(c.flip_h)
						rect.pos.x-=cell_size.x;
					else
						rect.pos.x+=cell_size.x;
				} else {
					if(c.flip_v)
						rect.pos.y-=cell_size.y;
					else
						rect.pos.y+=cell_size.y;
				}
				
			} else if (tile_origin==TILE_ORIGIN_CENTER) {
				rect.pos+=tcenter;

				Vector2 center = (s/2) - tile_ofs;
				center_ofs=tcenter-(s/2);

				if (c.flip_h)
					rect.pos.x-=s.x-center.x;
				else
					rect.pos.x-=center.x;

				if (c.flip_v)
					rect.pos.y-=s.y-center.y;
				else
					rect.pos.y-=center.y;
			}


			if (r==Rect2()) {
				tex->draw_rect(canvas_item,rect,false,Color(1,1,1),c.transpose);
			} else {
				tex->draw_rect_region(canvas_item,rect,r,Color(1,1,1),c.transpose);
			}

			Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);


			for(int i=0;i<shapes.size();i++) {

				Ref<Shape2D> shape = shapes[i];
				if (shape.is_valid()) {

					Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
					Matrix32 xform;
					xform.set_origin(offset.floor());

					_fix_cell_transform(xform,c,shape_ofs+center_ofs,s);

					if (debug_canvas_item) {
						vs->canvas_item_add_set_transform(debug_canvas_item,xform);
						shape->draw(debug_canvas_item,debug_collision_color);

					}
					ps->body_add_shape(q.body,shape->get_rid(),xform);
					ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y));

				}
			}

			if (debug_canvas_item) {
				vs->canvas_item_add_set_transform(debug_canvas_item,Matrix32());
			}

			if (navigation) {
				Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id);
				if (navpoly.is_valid()) {
					Vector2 npoly_ofs = tile_set->tile_get_navigation_polygon_offset(c.id);
					Matrix32 xform;
					xform.set_origin(offset.floor()+q.pos);
					_fix_cell_transform(xform,c,npoly_ofs+center_ofs,s);


					int pid = navigation->navpoly_create(navpoly,nav_rel * xform);

					Quadrant::NavPoly np;
					np.id=pid;
					np.xform=xform;
					q.navpoly_ids[E->key()]=np;
				}
			}


			Ref<OccluderPolygon2D> occluder=tile_set->tile_get_light_occluder(c.id);
			if (occluder.is_valid()) {

				Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
				Matrix32 xform;
				xform.set_origin(offset.floor()+q.pos);
				_fix_cell_transform(xform,c,occluder_ofs+center_ofs,s);

				RID orid = VS::get_singleton()->canvas_light_occluder_create();
				VS::get_singleton()->canvas_light_occluder_set_transform(orid,get_global_transform() * xform);
				VS::get_singleton()->canvas_light_occluder_set_polygon(orid,occluder->get_rid());
				VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid,get_canvas());
				VS::get_singleton()->canvas_light_occluder_set_light_mask(orid,occluder_light_mask);
				Quadrant::Occluder oc;
				oc.xform=xform;
				oc.id=orid;
				q.occluder_instances[E->key()]=oc;
			}
		}

		dirty_quadrant_list.remove( dirty_quadrant_list.first() );
		quadrant_order_dirty=true;
	}



	pending_update=false;

	if (quadrant_order_dirty) {

		for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {

			Quadrant &q=E->get();
			for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) {

				VS::get_singleton()->canvas_item_raise(E->get());
			}
		}

		quadrant_order_dirty=false;
	}

	for(int i=0;i<get_child_count();i++) {

		CanvasItem *c=get_child(i)->cast_to<CanvasItem>();

		if (c)
			VS::get_singleton()->canvas_item_raise(c->get_canvas_item());
	}

	_recompute_rect_cache();

}
Esempio n. 11
0
void Skeleton::_notification(int p_what) {

	switch (p_what) {

		case NOTIFICATION_ENTER_WORLD: {

			if (dirty) {

				dirty = false;
				_make_dirty(); // property make it dirty
			}

		} break;
		case NOTIFICATION_EXIT_WORLD: {

		} break;
		case NOTIFICATION_TRANSFORM_CHANGED: {

			if (dirty)
				break; //will be eventually updated

			//if moved, just update transforms
			VisualServer *vs = VisualServer::get_singleton();
			const Bone *bonesptr = bones.ptr();
			int len = bones.size();
			Transform global_transform = get_global_transform();
			Transform global_transform_inverse = global_transform.affine_inverse();

			for (int i = 0; i < len; i++) {

				const Bone &b = bonesptr[i];
				vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse));
			}
		} break;
		case NOTIFICATION_UPDATE_SKELETON: {

			VisualServer *vs = VisualServer::get_singleton();
			Bone *bonesptr = bones.ptrw();
			int len = bones.size();

			vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens

			// pose changed, rebuild cache of inverses
			if (rest_global_inverse_dirty) {

				// calculate global rests and invert them
				for (int i = 0; i < len; i++) {
					Bone &b = bonesptr[i];
					if (b.parent >= 0)
						b.rest_global_inverse = bonesptr[b.parent].rest_global_inverse * b.rest;
					else
						b.rest_global_inverse = b.rest;
				}
				for (int i = 0; i < len; i++) {
					Bone &b = bonesptr[i];
					b.rest_global_inverse.affine_invert();
				}

				rest_global_inverse_dirty = false;
			}

			Transform global_transform = get_global_transform();
			Transform global_transform_inverse = global_transform.affine_inverse();

			for (int i = 0; i < len; i++) {

				Bone &b = bonesptr[i];

				if (b.disable_rest) {
					if (b.enabled) {

						Transform pose = b.pose;
						if (b.custom_pose_enable) {

							pose = b.custom_pose * pose;
						}

						if (b.parent >= 0) {

							b.pose_global = bonesptr[b.parent].pose_global * pose;
						} else {

							b.pose_global = pose;
						}
					} else {

						if (b.parent >= 0) {

							b.pose_global = bonesptr[b.parent].pose_global;
						} else {

							b.pose_global = Transform();
						}
					}

				} else {
					if (b.enabled) {

						Transform pose = b.pose;
						if (b.custom_pose_enable) {

							pose = b.custom_pose * pose;
						}

						if (b.parent >= 0) {

							b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
						} else {

							b.pose_global = b.rest * pose;
						}
					} else {

						if (b.parent >= 0) {

							b.pose_global = bonesptr[b.parent].pose_global * b.rest;
						} else {

							b.pose_global = b.rest;
						}
					}
				}

				b.transform_final = b.pose_global * b.rest_global_inverse;
				vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse));

				for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {

					Object *obj = ObjectDB::get_instance(E->get());
					ERR_CONTINUE(!obj);
					Spatial *sp = Object::cast_to<Spatial>(obj);
					ERR_CONTINUE(!sp);
					sp->set_transform(b.pose_global);
				}
			}

			dirty = false;
		} break;
	}
}