Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;

}
Пример #4
0
void TileMapEditor::_canvas_draw() {

	if (!node)
		return;

	Matrix32 cell_xf = node->get_cell_transform();

	Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
	Matrix32 xform_inv = xform.affine_inverse();


	Size2 screen_size=canvas_item_editor->get_size();
	{
		Rect2 aabb;
		aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
		aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
		Rect2i si=aabb.grow(1.0);

		if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {

			int max_lines=2000; //avoid crash if size too smal

			for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {

				Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
				Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));

				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
				canvas_item_editor->draw_line(from,to,col,1);
				if (max_lines--==0)
					break;
			}
		} else {

			int max_lines=10000; //avoid crash if size too smal

			for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {

				for (int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {

					Vector2 ofs;
					if (ABS(j)&1) {
						ofs=cell_xf[0]*0.5;
					}

					Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
					Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
					canvas_item_editor->draw_line(from,to,col,1);

					if (max_lines--==0)
						break;

				}

			}
		}

		int max_lines=10000; //avoid crash if size too smal

		if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {

			for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {

				Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
				Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));

				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
				canvas_item_editor->draw_line(from,to,col,1);

				if (max_lines--==0)
					break;

			}
		} else {


			for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {

				for (int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {

					Vector2 ofs;
					if (ABS(j)&1) {
						ofs=cell_xf[1]*0.5;
					}

					Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
					Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
					canvas_item_editor->draw_line(from,to,col,1);

					if (max_lines--==0)
						break;

				}
			}
		}
	}

	if (selection_active) {

		Vector<Vector2> points;
		points.push_back( xform.xform( node->map_to_world(( rectangle.pos ) )));
		points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,0)) ) ));
		points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,rectangle.size.y+1)) ) ));
		points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(0,rectangle.size.y+1)) ) ));

		canvas_item_editor->draw_colored_polygon(points, Color(0.2,0.8,1,0.4));
	}

	if (mouse_over){

		Vector2 endpoints[4]={
			node->map_to_world(over_tile, true),
			node->map_to_world((over_tile+Point2(1,0)), true),
			node->map_to_world((over_tile+Point2(1,1)), true),
			node->map_to_world((over_tile+Point2(0,1)), true)
		};

		for (int i=0;i<4;i++) {
			if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
				endpoints[i]+=cell_xf[0]*0.5;
			if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
				endpoints[i]+=cell_xf[1]*0.5;
			endpoints[i]=xform.xform(endpoints[i]);
		}
		Color col;
		if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
			col=Color(0.2,0.8,1.0,0.8);
		else
			col=Color(1.0,0.4,0.2,0.8);

		for (int i=0;i<4;i++)
			canvas_item_editor->draw_line(endpoints[i],endpoints[(i+1)%4],col,2);


		if (tool==TOOL_SELECTING || tool==TOOL_PICKING || tool==TOOL_BUCKET) {

			return;
		}

		if (tool==TOOL_LINE_PAINT) {

			if (paint_undo.empty())
				return;

			int id = get_selected_tile();

			if (id==TileMap::INVALID_CELL)
				return;

			for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {

				_draw_cell(id, E->key(), flip_h, flip_v, transpose, xform);
			}

		} else if (tool==TOOL_RECTANGLE_PAINT) {

			int id = get_selected_tile();

			if (id==TileMap::INVALID_CELL)
				return;

			for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
				for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {

					_draw_cell(id, Point2i(j, i), flip_h, flip_v, transpose, xform);
				}
			}
		} else if (tool==TOOL_DUPLICATING) {

			if (copydata.empty())
				return;

			Ref<TileSet> ts = node->get_tileset();

			if (ts.is_null())
				return;

			Point2 ofs = over_tile-rectangle.pos;

			for (List<TileData>::Element *E=copydata.front();E;E=E->next()) {

				if (!ts->has_tile(E->get().cell))
					continue;

				TileData tcd = E->get();

				_draw_cell(tcd.cell, tcd.pos+ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform);
			}

			Rect2i duplicate=rectangle;
			duplicate.pos=over_tile;

			Vector<Vector2> points;
			points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));

			canvas_item_editor->draw_colored_polygon(points, Color(0.2,1.0,0.8,0.2));

		} else {

			int st = get_selected_tile();

			if (st==TileMap::INVALID_CELL)
				return;

			_draw_cell(st, over_tile, flip_h, flip_v, transpose, xform);
		}
	}
}
Пример #5
0
bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, 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,false);

    Rect2 aabb = p_xform.xform(shape->get_aabb());
    aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
    aabb=aabb.grow(p_margin);

    //if (p_motion!=Vector2())
    //	print_line(p_motion);

    int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

    float best_safe=1;
    float best_unsafe=1;

    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; //ignore excluded


        const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
        int shape_idx=space->intersection_query_subindex_results[i];


        /*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {

        	const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
        	if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) {
        		print_line("failed in motion dir");
        		continue;
        	}
        }*/


        Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
        //test initial overlap, does it collide if going all the way?
        if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
            continue;
        }


        //test initial overlap
        if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {

            if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
                //if one way collision direction ignore initial overlap
                const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
                if (body->get_one_way_collision_direction()!=Vector2()) {
                    continue;
                }
            }

            return false;
        }


        //just do kinematic solving
        float low=0;
        float hi=1;
        Vector2 mnormal=p_motion.normalized();

        for(int i=0; i<8; i++) { //steps should be customizable..

            Matrix32 xfa = p_xform;
            float ofs = (low+hi)*0.5;

            Vector2 sep=mnormal; //important optimization for this to work fast enough
            bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);

            if (collided) {

                hi=ofs;
            } else {

                low=ofs;
            }
        }

        if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {

            const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
            if (body->get_one_way_collision_direction()!=Vector2()) {

                Vector2 cd[2];
                Physics2DServerSW::CollCbkData cbk;
                cbk.max=1;
                cbk.amount=0;
                cbk.ptr=cd;
                cbk.valid_dir=body->get_one_way_collision_direction();
                cbk.valid_depth=body->get_one_way_collision_max_depth();

                Vector2 sep=mnormal; //important optimization for this to work fast enough
                bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*(hi+space->contact_max_allowed_penetration),col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),Physics2DServerSW::_shape_col_cbk,&cbk,&sep,p_margin);
                if (!collided || cbk.amount==0) {
                    continue;
                }

            }
        }


        if (low<best_safe) {
            best_safe=low;
            best_unsafe=hi;
        }

    }

    p_closest_safe=best_safe;
    p_closest_unsafe=best_unsafe;

    return true;


}
Пример #6
0
bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {

	Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape, false);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
	aabb = aabb.grow(p_margin);

	/*
	if (p_motion!=Vector2())
		print_line(p_motion);
	*/

	int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);

	real_t best_safe = 1;
	real_t best_unsafe = 1;

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

		if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
			continue;

		if (p_exclude.has(space->intersection_query_results[i]->get_self()))
			continue; //ignore excluded

		const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
		int shape_idx = space->intersection_query_subindex_results[i];

		/*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {

			const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
			if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) {
				print_line("failed in motion dir");
				continue;
			}
		}*/

		Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
		//test initial overlap, does it collide if going all the way?
		if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, p_margin)) {
			continue;
		}

		//test initial overlap
		if (CollisionSolver2DSW::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, p_margin)) {

			return false;
		}

		//just do kinematic solving
		real_t low = 0;
		real_t hi = 1;
		Vector2 mnormal = p_motion.normalized();

		for (int i = 0; i < 8; i++) { //steps should be customizable..

			real_t ofs = (low + hi) * 0.5;

			Vector2 sep = mnormal; //important optimization for this to work fast enough
			bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * ofs, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, &sep, p_margin);

			if (collided) {

				hi = ofs;
			} else {

				low = ofs;
			}
		}

		if (low < best_safe) {
			best_safe = low;
			best_unsafe = hi;
		}
	}

	p_closest_safe = best_safe;
	p_closest_unsafe = best_unsafe;

	return true;
}
Пример #7
0
void TileMapEditor::_canvas_draw() {

	if (!node)
		return;

	Size2 cell_size=node->get_cell_size();
	Matrix32 cell_xf = node->get_cell_transform();

	Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
	Matrix32 xform_inv = xform.affine_inverse();


	Size2 screen_size=canvas_item_editor->get_size();
	{
		Rect2 aabb;
		aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
		aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
		Rect2i si=aabb.grow(1.0);

		if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {

			for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {

				Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
				Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));

				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
				canvas_item_editor->draw_line(from,to,col,1);

			}
		} else {


			for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {

				for(int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {

					Vector2 ofs;
					if (ABS(j)&1) {
						ofs=cell_xf[0]*0.5;
					}

					Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
					Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
					canvas_item_editor->draw_line(from,to,col,1);
				}

			}
		}

		if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {

			for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {

				Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
				Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));

				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
				canvas_item_editor->draw_line(from,to,col,1);

			}
		} else {


			for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {

				for(int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {

					Vector2 ofs;
					if (ABS(j)&1) {
						ofs=cell_xf[1]*0.5;
					}

					Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
					Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
					canvas_item_editor->draw_line(from,to,col,1);
				}

			}



		}
/*
	for(int i=(si.pos.y/cell_size.y)-1;i<=(si.pos.y+si.size.y)/cell_size.y;i++) {

		int ofs = i*cell_size.y;
		Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
		canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);*/
	}


	if (selection_active) {

		Vector<Vector2> points;
		points.push_back( xform.xform( node->map_to_world(( selection.pos ) )));
		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,0)) ) ));
		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,selection.size.y+1)) ) ));
		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(0,selection.size.y+1)) ) ));
		Color col=Color(0.2,0.8,1,0.4);

		canvas_item_editor->draw_colored_polygon(points,col);
	}


	if (mouse_over){

		Vector2 endpoints[4]={

			( node->map_to_world(over_tile,true) ) ,
			( node->map_to_world((over_tile+Point2(1,0)),true ) ),
			( node->map_to_world((over_tile+Point2(1,1)),true ) ),
			( node->map_to_world((over_tile+Point2(0,1)),true ) )

		};

		for(int i=0;i<4;i++) {
			if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
				endpoints[i]+=cell_xf[0]*0.5;
			if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
				endpoints[i]+=cell_xf[1]*0.5;
			endpoints[i]=xform.xform(endpoints[i]);
		}
		Color col;
		if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
			col=Color(0.2,0.8,1.0,0.8);
		else
			col=Color(1.0,0.4,0.2,0.8);

		for(int i=0;i<4;i++)
			canvas_item_editor->draw_line(endpoints[i],endpoints[(i+1)%4],col,2);



		if (tool==TOOL_DUPLICATING) {

			Rect2i duplicate=selection;
			duplicate.pos=over_tile;


			Vector<Vector2> points;
			points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
			Color col=Color(0.2,1.0,0.8,0.4);

			canvas_item_editor->draw_colored_polygon(points,col);

		} else {

			Ref<TileSet> ts = node->get_tileset();


			if (ts.is_valid()) {

				int st = get_selected_tile();
				if (ts->has_tile(st)) {

					Ref<Texture> t = ts->tile_get_texture(st);
					if (t.is_valid()) {
						Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset();
						Rect2 r = ts->tile_get_region(st);
						Size2 sc = xform.get_scale();
						if (mirror_x->is_pressed())
							sc.x*=-1.0;
						if (mirror_y->is_pressed())
							sc.y*=-1.0;

						Rect2 rect;
						if (r==Rect2()) {
							rect=Rect2(from,t->get_size());
						} else {

							rect=Rect2(from,r.get_size());
						}


						if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) {
							rect.pos+=ts->tile_get_texture_offset(st);

						} else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_CENTER) {
							rect.pos+=node->get_cell_size()/2;
							Vector2 s = r.size;

							Vector2 center = (s/2) - ts->tile_get_texture_offset(st);


							if (mirror_x->is_pressed())
								rect.pos.x-=s.x-center.x;
							else
								rect.pos.x-=center.x;

							if (mirror_y->is_pressed())
								rect.pos.y-=s.y-center.y;
							else
								rect.pos.y-=center.y;
						}

						rect.pos=xform.xform(rect.pos);
						rect.size*=sc;

						if (r==Rect2()) {

							canvas_item_editor->draw_texture_rect(t,rect,false,Color(1,1,1,0.5),transpose->is_pressed());
						} else {

							canvas_item_editor->draw_texture_rect_region(t,rect,r,Color(1,1,1,0.5),transpose->is_pressed());
						}
					}
				}
			}

		}
	}



}
void CollisionPolygonEditor::_polygon_draw() {

	if (!node)
		return;

	Vector<Vector2> poly;

	if (wip_active)
		poly=wip;
	else
		poly=node->get_polygon();



	int len = poly.size();
	float depth = node->get_depth()*0.5;

	imgeom->clear();
	imgeom->set_material_override(line_material);
	imgeom->begin(Mesh::PRIMITIVE_LINES,Ref<Texture>());


	Rect2 rect;

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


		Vector2 p,p2;
		p = i==edited_point ? edited_point_pos : poly[i];
		if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
			p2=edited_point_pos;
		else
			p2 = poly[(i+1)%poly.size()];

		if (i==0)
			rect.pos=p;
		else
			rect.expand_to(p);

		Vector3 point = Vector3(p.x,p.y,depth);
		Vector3 next_point = Vector3(p2.x,p2.y,depth);

		imgeom->set_color(Color(1,0.3,0.1,0.8));
		imgeom->add_vertex(point);
		imgeom->set_color(Color(1,0.3,0.1,0.8));
		imgeom->add_vertex(next_point);

		//Color col=Color(1,0.3,0.1,0.8);
		//vpc->draw_line(point,next_point,col,2);
		//vpc->draw_texture(handle,point-handle->get_size()*0.5);
	}

	rect=rect.grow(1);

	AABB r;
	r.pos.x=rect.pos.x;
	r.pos.y=rect.pos.y;
	r.pos.z=depth;
	r.size.x=rect.size.x;
	r.size.y=rect.size.y;
	r.size.z=0;

	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos);
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0.3,0,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos);
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0.0,0.3,0));

	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)-Vector3(0.3,0,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)+Vector3(0,0.3,0));

	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)-Vector3(0,0.3,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)+Vector3(0.3,0,0));

	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+r.size);
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+r.size-Vector3(0.3,0,0));
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+r.size);
	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
	imgeom->add_vertex(r.pos+r.size-Vector3(0.0,0.3,0));

	imgeom->end();


	while(m->get_surface_count()) {
		m->surface_remove(0);
	}

	if (poly.size()==0)
		return;

	Array a;
	a.resize(Mesh::ARRAY_MAX);
	DVector<Vector3> va;
	{

		va.resize(poly.size());
		DVector<Vector3>::Write w=va.write();
		for(int i=0;i<poly.size();i++) {


			Vector2 p,p2;
			p = i==edited_point ? edited_point_pos : poly[i];

			Vector3 point = Vector3(p.x,p.y,depth);
			w[i]=point;
		}
	}
	a[Mesh::ARRAY_VERTEX]=va;
	m->add_surface(Mesh::PRIMITIVE_POINTS,a);
	m->surface_set_material(0,handle_material);

}
Пример #9
0
void Polygon2D::_notification(int p_what) {

	switch (p_what) {

		case NOTIFICATION_DRAW: {

			if (polygon.size() < 3)
				return;

			Skeleton2D *skeleton_node = NULL;
			if (has_node(skeleton)) {
				skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton));
			}

			ObjectID new_skeleton_id = 0;

			if (skeleton_node) {
				VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
				new_skeleton_id = skeleton_node->get_instance_id();
			} else {
				VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID());
			}

			if (new_skeleton_id != current_skeleton_id) {
				Object *old_skeleton = ObjectDB::get_instance(current_skeleton_id);
				if (old_skeleton) {
					old_skeleton->disconnect("bone_setup_changed", this, "_skeleton_bone_setup_changed");
				}

				if (skeleton_node) {
					skeleton_node->connect("bone_setup_changed", this, "_skeleton_bone_setup_changed");
				}

				current_skeleton_id = new_skeleton_id;
			}

			Vector<Vector2> points;
			Vector<Vector2> uvs;
			Vector<int> bones;
			Vector<float> weights;

			int len = polygon.size();
			if ((invert || polygons.size() == 0) && internal_vertices > 0) {
				//if no polygons are around, internal vertices must not be drawn, else let them be
				len -= internal_vertices;
			}

			if (len <= 0) {
				return;
			}
			points.resize(len);

			{

				PoolVector<Vector2>::Read polyr = polygon.read();
				for (int i = 0; i < len; i++) {
					points.write[i] = polyr[i] + offset;
				}
			}

			if (invert) {

				Rect2 bounds;
				int highest_idx = -1;
				float highest_y = -1e20;
				float sum = 0;

				for (int i = 0; i < len; i++) {
					if (i == 0)
						bounds.position = points[i];
					else
						bounds.expand_to(points[i]);
					if (points[i].y > highest_y) {
						highest_idx = i;
						highest_y = points[i].y;
					}
					int ni = (i + 1) % len;
					sum += (points[ni].x - points[i].x) * (points[ni].y + points[i].y);
				}

				bounds = bounds.grow(invert_border);

				Vector2 ep[7] = {
					Vector2(points[highest_idx].x, points[highest_idx].y + invert_border),
					Vector2(bounds.position + bounds.size),
					Vector2(bounds.position + Vector2(bounds.size.x, 0)),
					Vector2(bounds.position),
					Vector2(bounds.position + Vector2(0, bounds.size.y)),
					Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y + invert_border),
					Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y),
				};

				if (sum > 0) {
					SWAP(ep[1], ep[4]);
					SWAP(ep[2], ep[3]);
					SWAP(ep[5], ep[0]);
					SWAP(ep[6], points.write[highest_idx]);
				}

				points.resize(points.size() + 7);
				for (int i = points.size() - 1; i >= highest_idx + 7; i--) {

					points.write[i] = points[i - 7];
				}

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

					points.write[highest_idx + i + 1] = ep[i];
				}

				len = points.size();
			}

			if (texture.is_valid()) {

				Transform2D texmat(tex_rot, tex_ofs);
				texmat.scale(tex_scale);
				Size2 tex_size = texture->get_size();

				uvs.resize(len);

				if (points.size() == uv.size()) {

					PoolVector<Vector2>::Read uvr = uv.read();

					for (int i = 0; i < len; i++) {
						uvs.write[i] = texmat.xform(uvr[i]) / tex_size;
					}

				} else {
					for (int i = 0; i < len; i++) {
						uvs.write[i] = texmat.xform(points[i]) / tex_size;
					}
				}
			}

			if (skeleton_node && !invert && bone_weights.size()) {
				//a skeleton is set! fill indices and weights
				int vc = len;
				bones.resize(vc * 4);
				weights.resize(vc * 4);

				int *bonesw = bones.ptrw();
				float *weightsw = weights.ptrw();

				for (int i = 0; i < vc * 4; i++) {
					bonesw[i] = 0;
					weightsw[i] = 0;
				}

				for (int i = 0; i < bone_weights.size(); i++) {
					if (bone_weights[i].weights.size() != points.size()) {
						continue; //different number of vertices, sorry not using.
					}
					if (!skeleton_node->has_node(bone_weights[i].path)) {
						continue; //node does not exist
					}
					Bone2D *bone = Object::cast_to<Bone2D>(skeleton_node->get_node(bone_weights[i].path));
					if (!bone) {
						continue;
					}

					int bone_index = bone->get_index_in_skeleton();
					PoolVector<float>::Read r = bone_weights[i].weights.read();
					for (int j = 0; j < vc; j++) {
						if (r[j] == 0.0)
							continue; //weight is unpainted, skip
						//find an index with a weight
						for (int k = 0; k < 4; k++) {
							if (weightsw[j * 4 + k] < r[j]) {
								//this is less than this weight, insert weight!
								for (int l = 3; l > k; l--) {
									weightsw[j * 4 + l] = weightsw[j * 4 + l - 1];
									bonesw[j * 4 + l] = bonesw[j * 4 + l - 1];
								}
								weightsw[j * 4 + k] = r[j];
								bonesw[j * 4 + k] = bone_index;
								break;
							}
						}
					}
				}

				//normalize the weights
				for (int i = 0; i < vc; i++) {
					float tw = 0;
					for (int j = 0; j < 4; j++) {
						tw += weightsw[i * 4 + j];
					}
					if (tw == 0)
						continue; //unpainted, do nothing

					//normalize
					for (int j = 0; j < 4; j++) {
						weightsw[i * 4 + j] /= tw;
					}
				}
			}

			Vector<Color> colors;
			if (vertex_colors.size() == points.size()) {
				colors.resize(len);
				PoolVector<Color>::Read color_r = vertex_colors.read();
				for (int i = 0; i < len; i++) {
					colors.write[i] = color_r[i];
				}
			} else {
				colors.push_back(color);
			}

			//			Vector<int> indices = Geometry::triangulate_polygon(points);
			//			VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());

			if (invert || polygons.size() == 0) {
				Vector<int> indices = Geometry::triangulate_polygon(points);
				VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
			} else {
				//draw individual polygons
				Vector<int> total_indices;
				for (int i = 0; i < polygons.size(); i++) {
					PoolVector<int> src_indices = polygons[i];
					int ic = src_indices.size();
					if (ic < 3)
						continue;
					PoolVector<int>::Read r = src_indices.read();

					Vector<Vector2> tmp_points;
					tmp_points.resize(ic);

					for (int j = 0; j < ic; j++) {
						int idx = r[j];
						ERR_CONTINUE(idx < 0 || idx >= points.size());
						tmp_points.write[j] = points[r[j]];
					}
					Vector<int> indices = Geometry::triangulate_polygon(tmp_points);
					int ic2 = indices.size();
					const int *r2 = indices.ptr();

					int bic = total_indices.size();
					total_indices.resize(bic + ic2);
					int *w2 = total_indices.ptrw();

					for (int j = 0; j < ic2; j++) {
						w2[j + bic] = r[r2[j]];
					}
				}

				if (total_indices.size()) {
					VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
				}

#if 0
				//use splits
				Vector<int> loop;
				int sc = splits.size();
				PoolVector<int>::Read r = splits.read();


				print_line("has splits, amount " + itos(splits.size()));
				Vector<Vector<int> > loops;

				// find a point that can be used to begin, must not be in a split, and have to the left and right the same one
				// like this one -> x---o
				//                   \ / \ .
				//                    o---o
				int base_point = -1;
				{
					int current_point = -1;
					int base_point_prev_split = -1;


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

						//find if this point is in a split
						int split_index = -1;
						bool has_prev_split = false;
						int min_dist_to_end = 0x7FFFFFFF;

						for (int j = 0; j < sc; j += 2) {

							int split_pos = -1;
							int split_end = -1;

							if (r[j + 0] == i) { //found split in first point
								split_pos = r[j + 0];
								split_end = r[j + 1];
							} else if (r[j + 1] == i) { //found split in second point
								split_pos = r[j + 1];
								split_end = r[j + 0];
							}

							if (split_pos == split_end) {
								continue; //either nothing found or begin == end, this not a split in either case
							}

							if (j == base_point_prev_split) {
								has_prev_split = true;
							}

							//compute distance from split pos to split end in current traversal direction
							int dist_to_end = split_end > split_pos ? split_end - split_pos : (last - split_pos + split_end);

							if (dist_to_end < min_dist_to_end) {
								//always keep the valid split with the least distance to the loop
								min_dist_to_end = dist_to_end;
								split_index = j;
							}
						}

						if (split_index == -1) {
							current_point = i; //no split here, we are testing this point
						} else if (has_prev_split) {
							base_point = current_point; // there is a split and it contains the previous visited split, success
							break;
						} else {
							//invalidate current point and keep split
							current_point = -1;
							base_point_prev_split = split_index;
						}
					}
				}

				print_line("found base point: " + itos(base_point));

				if (base_point != -1) {

					int point = base_point;
					int last = base_point;
					//go through all the points, find splits
					do {

						int split;
						int last_dist_to_end = -1; //maximum valid distance to end

						do {

							loop.push_back(point); //push current point

							split = -1;
							int end = -1;

							int max_dist_to_end = 0;

							//find if this point is in a split
							for (int j = 0; j < sc; j += 2) {

								int split_pos = -1;
								int split_end = -1;

								if (r[j + 0] == point) { //match first split index
									split_pos = r[j + 0];
									split_end = r[j + 1];
								} else if (r[j + 1] == point) { //match second split index
									split_pos = r[j + 1];
									split_end = r[j + 0];
								}

								if (split_pos == split_end) {
									continue; //either nothing found or begin == end, this not a split in either case
								}

								//compute distance from split pos to split end
								int dist_to_end = split_end > split_pos ? split_end - split_pos : (points.size() - split_pos + split_end);

								if (last_dist_to_end != -1 && dist_to_end >= last_dist_to_end) {
									//distance must be shorter than in last iteration, means we've tested this before so ignore
									continue;
								} else if (dist_to_end > max_dist_to_end) {
									//always keep the valid point with the most distance (as long as it's valid)
									max_dist_to_end = dist_to_end;
									split = split_pos;
									end = split_end;
								}
							}

							if (split != -1) {
								//found a split!
								int from = end;

								//add points until last is reached
								while (true) {
									//find if point is in a split
									loop.push_back(from);

									if (from == last) {
										break;
									}

									from++;
									if (from >= points.size()) { //wrap if reached end
										from = 0;
									}

									if (from == loop[0]) {
										break; //end because we reached split source
									}
								}

								loops.push_back(loop); //done with this loop
								loop.clear();

								last_dist_to_end = max_dist_to_end;
								last = end; //algorithm can safely finish in this split point
							}

						} while (split != -1);

					} while (point != last);
				}

				if (loop.size() >=2 ) { //points remained
					//points remain
					loop.push_back(last); //no splits found, use last
					loops.push_back(loop);
				}

				print_line("total loops: " + itos(loops.size()));

				if (loops.size()) { //loops found
					Vector<int> indices;

					for (int i = 0; i < loops.size(); i++) {
						Vector<int> loop = loops[i];
						Vector<Vector2> vertices;
						vertices.resize(loop.size());
						for (int j = 0; j < vertices.size(); j++) {
							vertices.write[j] = points[loop[j]];
						}
						Vector<int> sub_indices = Geometry::triangulate_polygon(vertices);
						int from = indices.size();
						indices.resize(from + sub_indices.size());
						for (int j = 0; j < sub_indices.size(); j++) {
							indices.write[from + j] = loop[sub_indices[j]];
						}
					}

					VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
				}
#endif
			}

		} break;
	}
}
Пример #10
0
void GradientEdit::_notification(int p_what) {

	if (p_what == NOTIFICATION_ENTER_TREE) {
		if (!picker->is_connected("color_changed", this, "_color_changed")) {
			picker->connect("color_changed", this, "_color_changed");
		}
	}
	if (p_what == NOTIFICATION_DRAW) {

		int w = get_size().x;
		int h = get_size().y;

		if (w == 0 || h == 0)
			return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size

		int total_w = get_size().width - get_size().height - SPACING;

		//Draw checker pattern for ramp
		_draw_checker(0, 0, total_w, h);

		//Draw color ramp
		Gradient::Point prev;
		prev.offset = 0;
		if (points.size() == 0)
			prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points
		else
			prev.color = points[0].color; //Extend color of first point to the beginning.

		for (int i = -1; i < points.size(); i++) {

			Gradient::Point next;
			//If there is no next point
			if (i + 1 == points.size()) {
				if (points.size() == 0)
					next.color = Color(0, 0, 0); //Draw black rectangle if we have no points
				else
					next.color = points[i].color; //Extend color of last point to the end.
				next.offset = 1;
			} else {
				next = points[i + 1];
			}

			if (prev.offset == next.offset) {
				prev = next;
				continue;
			}

			Vector<Vector2> points;
			Vector<Color> colors;
			points.push_back(Vector2(prev.offset * total_w, h));
			points.push_back(Vector2(prev.offset * total_w, 0));
			points.push_back(Vector2(next.offset * total_w, 0));
			points.push_back(Vector2(next.offset * total_w, h));
			colors.push_back(prev.color);
			colors.push_back(prev.color);
			colors.push_back(next.color);
			colors.push_back(next.color);
			draw_primitive(points, colors, Vector<Point2>());
			prev = next;
		}

		//Draw point markers
		for (int i = 0; i < points.size(); i++) {

			Color col = points[i].color.contrasted();
			col.a = 0.9;

			draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col);
			Rect2 rect = Rect2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2, POINT_WIDTH, h / 2);
			draw_rect(rect, points[i].color, true);
			draw_rect(rect, col, false);
			if (grabbed == i) {
				rect = rect.grow(-1);
				if (has_focus()) {
					draw_rect(rect, Color(1, 0, 0, 0.9), false);
				} else {
					draw_rect(rect, Color(0.6, 0, 0, 0.9), false);
				}

				rect = rect.grow(-1);
				draw_rect(rect, col, false);
			}
		}

		//Draw "button" for color selector
		_draw_checker(total_w + SPACING, 0, h, h);
		if (grabbed != -1) {
			//Draw with selection color
			draw_rect(Rect2(total_w + SPACING, 0, h, h), points[grabbed].color);
		} else {
			//if no color selected draw grey color with 'X' on top.
			draw_rect(Rect2(total_w + SPACING, 0, h, h), Color(0.5, 0.5, 0.5, 1));
			draw_line(Vector2(total_w + SPACING, 0), Vector2(total_w + SPACING + h, h), Color(1, 1, 1, 0.6));
			draw_line(Vector2(total_w + SPACING, h), Vector2(total_w + SPACING + h, 0), Color(1, 1, 1, 0.6));
		}

		//Draw borders around color ramp if in focus
		if (has_focus()) {

			draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6));
			draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6));
			draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
			draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
		}
	}

	if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {

		if (!is_visible()) {
			grabbing = false;
		}
	}
}
Пример #11
0
bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, 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,false);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
	aabb=aabb.grow(p_margin);

	//if (p_motion!=Vector2())
	//	print_line(p_motion);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	float best_safe=1;
	float best_unsafe=1;

	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; //ignore excluded


		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];


		Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
		//test initial overlap, does it collide if going all the way?
		if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
			continue;
		}


		//test initial overlap
		if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {

			return false;
		}


		//just do kinematic solving
		float low=0;
		float hi=1;
		Vector2 mnormal=p_motion.normalized();

		for(int i=0;i<8;i++) { //steps should be customizable..

			Matrix32 xfa = p_xform;
			float ofs = (low+hi)*0.5;

			Vector2 sep=mnormal; //important optimization for this to work fast enough
			bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);

			if (collided) {

				hi=ofs;
			} else {

				low=ofs;
			}
		}

		if (low<best_safe) {
			best_safe=low;
			best_unsafe=hi;
		}

	}

	p_closest_safe=best_safe;
	p_closest_unsafe=best_unsafe;

	return true;


}
Пример #12
0
void Polygon2D::_notification(int p_what) {


	switch(p_what) {

		case NOTIFICATION_DRAW: {

			if (polygon.size()<3)
				return;

			Vector<Vector2> points;
			Vector<Vector2> uvs;

			points.resize(polygon.size());

			int len = points.size();
			{

				DVector<Vector2>::Read polyr =polygon.read();
				for(int i=0;i<len;i++) {
					points[i]=polyr[i]+offset;
				}
			}

			if (invert) {

				Rect2 bounds;
				int highest_idx=-1;
				float highest_y=-1e20;
				float sum=0;

				for(int i=0;i<len;i++) {
					if (i==0)
						bounds.pos=points[i];
					else
						bounds.expand_to(points[i]);
					if (points[i].y>highest_y) {
						highest_idx=i;
						highest_y=points[i].y;
					}
					int ni=(i+1)%len;
					sum+=(points[ni].x-points[i].x)*(points[ni].y+points[i].y);
				}

				bounds=bounds.grow(invert_border);

				Vector2 ep[7]={
					Vector2(points[highest_idx].x,points[highest_idx].y+invert_border),
					Vector2(bounds.pos+bounds.size),
					Vector2(bounds.pos+Vector2(bounds.size.x,0)),
					Vector2(bounds.pos),
					Vector2(bounds.pos+Vector2(0,bounds.size.y)),
					Vector2(points[highest_idx].x-CMP_EPSILON,points[highest_idx].y+invert_border),
					Vector2(points[highest_idx].x-CMP_EPSILON,points[highest_idx].y),
				};


				if (sum>0) {
					SWAP(ep[1],ep[4]);
					SWAP(ep[2],ep[3]);
					SWAP(ep[5],ep[0]);
					SWAP(ep[6],points[highest_idx]);
				}

				points.resize(points.size()+7);
				for(int i=points.size()-1;i>=highest_idx+7;i--) {

					points[i]=points[i-7];
				}

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

					points[highest_idx+i+1]=ep[i];
				}


				len=points.size();

			}

			if (texture.is_valid()) {

				Matrix32 texmat(tex_rot,tex_ofs);
				texmat.scale(tex_scale);
				Size2 tex_size=Vector2(1,1);

				tex_size=texture->get_size();
				uvs.resize(points.size());

				if (points.size()==uv.size()) {

					DVector<Vector2>::Read uvr = uv.read();

					for(int i=0;i<len;i++) {
						uvs[i]=texmat.xform(uvr[i])/tex_size;
					}

				} else {
					for(int i=0;i<len;i++) {
						uvs[i]=texmat.xform(points[i])/tex_size;
					}
				}

			}


			Vector<Color> colors;
			colors.push_back(color);
			Vector<int> indices = Geometry::triangulate_polygon(points);

			VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(),indices,points,colors,uvs,texture.is_valid()?texture->get_rid():RID());

		} break;
	}
}