Example #1
0
void STGGeneric::makeChildren(SphereTree *st, int node, int level, const SurfaceRep &surRep) const{
  //  get the error of the parent
  Sphere parS = st->nodes.index(node);
  double parErr = eval->evalSphere(parS);

  //  get minimum bounding sphere for points to give to reducer
  Sphere boundingSphere;
  SFWhite::makeSphere(&boundingSphere, *surRep.getSurPts());

  //  generate the set of child spheres
  Array<Sphere> initChildren, children;
  reducer->getSpheres(&initChildren, st->degree, surRep, &boundingSphere, parErr);

  //  do sphere refit - local optimisation
  if (useRefit){
    OUTPUTINFO("Refitting\n");
    SOPerSphere perSphere;
    perSphere.numIter = 3;
    perSphere.eval = eval;
    perSphere.optimise(&initChildren, surRep);
    }

  //  apply optimiser if required
  if (optimiser && (maxOptLevel < 0 || level <= maxOptLevel))
    optimiser->optimise(&initChildren, surRep, -1, &parS, level-1);

  //  remove redundent spheres
  RELargest reLargest;
  if (!reLargest.reduceSpheres(&children, initChildren, surRep))
    children.clone(initChildren);

  int numChildren = children.getSize();
  if (numChildren == 0)
    return;

  //  get the points that this node covers
  const Array<Surface::Point> *surPts = surRep.getSurPts();
  int numPts = surPts->getSize();

  //  info for areas to be covered by each sphere
  Array<Array<Surface::Point> > subPts(numChildren);
  Array<bool> covered(numPts);
  covered.clear();

  //  make the divisions between the children
  SurfaceDivision surDiv;
  surDiv.setup(children, surPts);

  //  do the children
  int firstChild = st->getFirstChild(node);
  for (int i = 0; i < numChildren; i++){
    //  get sphere
    Sphere s = children.index(i);

    //  list the points in the sphere
    Array<int> listPoints;
    surRep.listContainedPoints(&listPoints, NULL, s, NULL);
    int numList = listPoints.getSize();

    //  filter points
    Array<Surface::Point> *filterPts = &subPts.index(i);
    filterPts->resize(0);
    for (int j = 0; j < numList; j++){
      //  get point
      int pI = listPoints.index(j);
      Surface::Point p = surPts->index(pI);

      //  check if it's in the region
      if (surDiv.pointInRegion(p.p, i)){
        covered.index(j) = true;
        filterPts->addItem() = p;
        }
      }
    }

  //  count/cover uncovered points
  for (int i = 0; i < numPts; i++){
    if (!covered.index(i)){
      //  get the point
      Point3D p = surPts->index(i).p;

      //  find the closest sphere
      int closestJ = -1;
      float closestD = 0;
      for (int j = 0; j < numChildren;  j++){
        Sphere s = children.index(j);
        float d = p.distance(s.c) - s.r;
        if (d < closestD){
          closestJ = j;
          closestD = d;
          }
        }

      subPts.index(closestJ).addItem() = surPts->index(i);
      }
    }

  //  store spheres & recurse to children 
  int childNum = firstChild;
  for (int i = 0; i < numChildren; i++){
    if (subPts.index(i).getSize() > 1){
      //  recreate the sphere
      Sphere s = children.index(i);

      //  add sphere to tree
      st->nodes.index(childNum).c = s.c;
      st->nodes.index(childNum).r = s.r;

      if (level < st->levels-1 && numChildren > 1){
        const Array<Surface::Point> *pts = &subPts.index(i);

        //  make cells to have 10 pts each, most will have alot more
        int numCells = pts->getSize() / PTS_PER_CELL;
        int gridDim = ceil(pow(numCells, 1.0 / 3.0));
        OUTPUTINFO("numCells = %d, gridDim = %d\n", numCells, gridDim);

        //  make children by recursion
        SurfaceRep subRep;
        subRep.setup(*pts, gridDim);

        makeChildren(st, childNum, level+1, subRep);
        }

      childNum++;
      }
    }

  //  NULL out the rest of the spheres
  for (int i = childNum; i < st->degree; i++)
    st->initNode(firstChild+i, level+1);
}
Example #2
0
Array<int> TriangleSoup::nonmanifold_nodes(bool allow_boundary) const {
  Array<int> nonmanifold;
  Nested<const int> incident_elements = this->incident_elements();
  Array<Vector<int,2>> ring;
  Hashtable<int,Vector<int,2>> neighbors(32); // prev,next for each node in the ring
  const Vector<int,2> none(-1,-1);
  for (int i=0;i<incident_elements.size();i++) {
    RawArray<const int> incident = incident_elements[i];
    if (!incident.size())
      continue;
    // Collect oriented boundary segments of the one ring
    ring.clear();
    ring.resize(incident.size(),uninit);
    for (int t=0;t<incident.size();t++) {
      Vector<int,3> tri = elements[incident[t]];
      if (tri.x==tri.y || tri.x==tri.z || tri.y==tri.z)
        goto bad;
      ring[t] = tri.x==i?vec(tri.y,tri.z):tri.y==i?vec(tri.z,tri.x):vec(tri.x,tri.y);
    }
    // Determine topology
    neighbors.clear();
    for (int t=0;t<ring.size();t++) {
      Vector<int,2>& nx = neighbors.get_or_insert(ring[t].x,none);
      if (nx.y>=0) goto bad; // node already has a next
      nx.y = ring[t].y;
      Vector<int,2>& ny = neighbors.get_or_insert(ring[t].y,none);
      if (ny.x>=0) goto bad; // node already has a prev
      ny.x = ring[t].x;
    }
    // At this point the ring is definitely a 1-manifold with boundary, possibly consisting of many component curves.
    if (neighbors.size()==ring.size()) { // All components are closed loops
      // Ensure there's only component by checking the size of one of them
      int start = ring[0].x, node = ring[0].y, steps = ring.size()-2;
      for (int j=0;j<steps;j++) {
        node = neighbors.get(node).y;
        if (node==start)
          goto bad;
      }
    } else if (neighbors.size()>ring.size()+1) // There are least two open curves
      goto bad;
    else { // There's exactly one open curve
      if (!allow_boundary)
        goto bad;
      // Ensure there's only one component by checking the size of one of them
      int middle = ring[0].x, count = 2;
      for (int start=middle;;) {
        start = neighbors.get(start).x;
        if (start<0) break;
        if (start==middle) goto bad; // Loop is closed, so there must be two components
        count++;
      }
      for (int end=ring[0].y;;) {
        end = neighbors.get(end).y;
        if (end<0) break;
        // No need to check for middle since we know the curve is open
        count++;
      }
      if (count!=neighbors.size())
        goto bad;
    }
    continue; // manifold node
    bad: nonmanifold.append(i);
  }
  return nonmanifold;
}
Example #3
0
//  generate breadth first
void STGGeneric::constructTree(SphereTree *st) const{
  CHECK_DEBUG0(st != NULL && st->degree > 1 && st->levels >= 1);
  CHECK_DEBUG0(reducer != NULL);
  CHECK_DEBUG0(eval != NULL);
  CHECK_DEBUG0(surfacePoints != NULL);

  //  NULL out the entire tree
  st->initNode(0);

  //  make cells to have 10 pts each, most will have alot more
  int numCells = surfacePoints->getSize() / PTS_PER_CELL;
  int gridDim = ceil(pow(numCells, 1.0 / 3.0));
  OUTPUTINFO("numCells = %d, gridDim = %d\n", numCells, gridDim);

  SurfaceRep surRep;
  surRep.setup(*surfacePoints, gridDim);

  //  bounding sphere for root - should use vertices
  SFWhite::makeSphere(&st->nodes.index(0), *surfacePoints);

  //  list of points to be covered by each node
  unsigned long start, num;
  st->getRow(&start, &num, st->levels-1);
  Array<Array<int>/**/> pointsInSpheres;
  pointsInSpheres.resize(st->nodes.getSize() - num);

  //  initialise the list for the first node
  int numPts = surfacePoints->getSize();
  Array<int> *list0 = &pointsInSpheres.index(0);
  list0->resize(numPts);
  for (int i = 0; i < numPts; i++)
    list0->index(i) = i;

  //  process the remaining levels
  int numLeaves = 0;
  for (int level = 0; level < st->levels-1; level++){
    //  get the positions of the nodes
    unsigned long start, num;
    st->getRow(&start, &num, level);

    //  update samples etc. for this level
    reducer->setupForLevel(level, st->degree, &surRep);

    //  get the errors for all the spheres in that level
    int numActualSpheres = 0;
    double averageError = 0;
    Array<double> sphereErrors(num);
    for (int i = 0; i < num; i++){
      Sphere s = st->nodes.index(start+i);
      if (s.r >= 0){
        double err = eval->evalSphere(s);
        sphereErrors.index(i) = err;
        averageError += err;
        numActualSpheres++;
        }
      else 
        sphereErrors.index(i) = -1;
      }
    averageError /= numActualSpheres;
    if (level != 0 && numActualSpheres <= 1){
      numLeaves++;
      continue;     //  there is only one sphere here - will never improve
      }

    //  process each node's to make children
    int maxNode = -1;
    double maxR = -1;
    int levelChildren = 0;
    for (int nodeI = 0; nodeI < num; nodeI++){
      //OUTPUTINFO("Level = %d, node = %d\n", level, nodeI);
      printf("Level = %d, node = %d\n", level, nodeI);

      int node = nodeI + start;
      if (st->nodes.index(node).r <= 0){
          OUTPUTINFO("R = %f\n", st->nodes.index(node).r);
          st->initNode(node);
          continue;
          }

/*
      //  hack to do largest sphere at each run - gives guide to good params
      double r = st->nodes.index(node).r;
      if (r > maxR){
        maxR = r;
        maxNode = node;
        }
      }

      nodeI = maxNode - start;
      int node = maxNode;{
      //  end hack
*/

      //  make the set of surface poitns to be covered by this sphere
      Array<int> *selPtsI = &pointsInSpheres.index(node);
      int numSelPts = selPtsI->getSize();

      if (numSelPts <= 0)
        break;

      Array<Surface::Point> selPts(numSelPts);
      for (int i = 0; i < numSelPts; i++)
        selPts.index(i) = surfacePoints->index(selPtsI->index(i));

      //  get filter sphere
      Sphere s;
      SFWhite::makeSphere(&s, selPts);

      //  make cells to have 10 pts each, most will have alot more
      int numCells = numSelPts / PTS_PER_CELL;
      int gridDim = ceil(pow(numCells, 1.0 / 3.0));
      OUTPUTINFO("%d Points\n", numSelPts);
      OUTPUTINFO("numCells = %d, gridDim = %d\n", numCells, gridDim);

      //  make new SurfaceRepresentation
      SurfaceRep subRep;
      subRep.setup(selPts, gridDim);

      //  compute error for this sphere
      double err = sphereErrors.index(nodeI);
      if (err > averageError)
        err = averageError;  //  improve the bad ones a bit more

      //  generate the children nodes
      Array<Sphere> initChildren, children;
      reducer->getSpheres(&initChildren, st->degree, subRep, &s, err);

      //  apply optimiser if required
      if (optimiser && (maxOptLevel < 0 || level <= maxOptLevel)){
printf("RUNNING OPTIMISER...\n");
        optimiser->optimise(&initChildren, subRep, -1, &s, level);
printf("DONE OPTIMISING...\n");
        }

      //  do sphere refit - local optimisation
      if (useRefit){
        OUTPUTINFO("Refitting\n");
        SOPerSphere perSphere;
        perSphere.numIter = 3;
        perSphere.eval = eval;
        perSphere.optimise(&initChildren, subRep);
        }

      //  remove redundent spheres
      RELargest reLargest;
      if (!reLargest.reduceSpheres(&children, initChildren, subRep))
        children.clone(initChildren);

      //  setup the node's sub-division (make the regions to be covered by children)
      //subDivs.index(node).setup(children, &selPts);
      SurfaceDivision surDiv;
      surDiv.setup(children, &selPts);

      //  list of points that are covered
      Array<bool> covered(numSelPts);
      covered.clear();

      //  create the new nodes and their the points to cover
      int numChildren = children.getSize();
      int firstChild = st->getFirstChild(node);
      levelChildren += numChildren;
      for (int i = 0; i < numChildren; i++){
        int childNum = firstChild + i;

        //  get sphere
        const Sphere& s = children.index(i);

        //  add sphere to tree
        st->nodes.index(childNum).c = s.c;
        st->nodes.index(childNum).r = s.r;

        if (level < st->levels-2){
          //  get the points in this sphere
          Array<int> pointsInS;
          subRep.listContainedPoints(&pointsInS, NULL, s);
          int numInS = pointsInS.getSize();

          //  populate list of points in sphere
          Array<int> *pointsToCover = &pointsInSpheres.index(childNum);
          pointsToCover->resize(0);   //  just in case
          for (int j = 0; j < numInS; j++){
            int pI = pointsInS.index(j);
            if (surDiv.pointInRegion(selPts.index(pI).p, i)){
              pointsToCover->addItem() = selPtsI->index(pI);
              covered.index(pI) = true;
              }
            }
          }
        }

      //  assign uncovered points
      if (numChildren > 0 && level < st->levels-2){
        for (int i = 0; i < numSelPts; i++){
          if (!covered.index(i)){
            //  get point
            const Point3D& pt = selPts.index(i).p;

            //  find the sphere
            int minJ = -1;
            float minD = FLT_MAX;
            for (int j = 0; j < numChildren; j++){
              const Sphere& s = children.index(j);
              float d = pt.distance(s.c);// - s.r;
              if (d < minD){
                minD = d;
                minJ = j;
                }
              }

            //  add the point to the sphere's list
            pointsInSpheres.index(firstChild+minJ).addItem() = selPtsI->index(i);
            }
          }
        }

      //  save after each child set
      //st->saveSphereTree("saved.sph");
      }

    //  save after each level
    //st->saveSphereTree("saved.sph");

    //  see if we need to add another level
    if (level == st->levels - 2 && minLeaves > 0 && numLeaves + levelChildren < minLeaves){
      //  grow the tree
      OUTPUTINFO("Growing the tree : %d-->%d\n", st->levels, st->levels+1);
      OUTPUTINFO("New Nodes : %d-->", st->nodes.getSize());
      st->growTree(st->levels+1);
      OUTPUTINFO("%d\n", st->nodes.getSize());
      }
    }
}
void CompressorPVR::compress(AlphaMode alphaMode, uint w, uint h, uint d, const float * data, TaskDispatcher * dispatcher, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
{
    EPVRTColourSpace color_space = ePVRTCSpacelRGB;

    //pvrtexture::PixelType src_pixel_type = pvrtexture::PixelType('b','g','r','a',8,8,8,8);
    pvrtexture::PixelType src_pixel_type = pvrtexture::PixelType('r','g','b',0,8,8,8,0);
    pvrtexture::CPVRTextureHeader header(src_pixel_type.PixelTypeID, w, h, d, 1/*num mips*/, 1/*num array*/, 1/*num faces*/, color_space, ePVRTVarTypeUnsignedByteNorm);

    /*
    uint count = w * h * d;
    Array<Color32> tmp;
    tmp.resize(count);

    for (uint i = 0; i < count; i++) {
        tmp[i] = toColor32(Vector4(data[0*count + i], data[1*count + i], data[2*count + i], data[3*count + i]));
    }
    */

    uint count = w * h * d;
    Array<uint8> tmp;
    tmp.resize(3 * count);

    for (uint i = 0; i < count; i++) {
        tmp[3*i+0] = data[0*count + i] * 255.0f;
        tmp[3*i+1] = data[1*count + i] * 255.0f;
        tmp[3*i+2] = data[2*count + i] * 255.0f;
    }

    pvrtexture::CPVRTexture texture(header, tmp.buffer());

    pvrtexture::PixelType dst_pixel_type = pvrtexture::PixelType(ePVRTPF_PVRTCI_2bpp_RGB);

    if (compressionOptions.format == Format_PVR_2BPP_RGB) dst_pixel_type = pvrtexture::PixelType(ePVRTPF_PVRTCI_2bpp_RGB);
    else if (compressionOptions.format == Format_PVR_4BPP_RGB) dst_pixel_type = pvrtexture::PixelType(ePVRTPF_PVRTCI_4bpp_RGB);
    else if (compressionOptions.format == Format_PVR_2BPP_RGBA) dst_pixel_type = pvrtexture::PixelType(ePVRTPF_PVRTCI_2bpp_RGBA);
    else if (compressionOptions.format == Format_PVR_4BPP_RGBA) dst_pixel_type = pvrtexture::PixelType(ePVRTPF_PVRTCI_4bpp_RGBA);

    bool success = pvrtexture::Transcode(texture, dst_pixel_type, ePVRTVarTypeUnsignedByteNorm, color_space, pvrtexture::ePVRTCNormal, false);

    if (success) {
        uint size = 0;
        if (compressionOptions.format == Format_PVR_2BPP_RGB || compressionOptions.format == Format_PVR_2BPP_RGBA) {
            // 2 bpp
            const uint bpp = 2u;
            const uint block_size = 8u * 4u;
            const uint size_factor=(block_size*bpp)>>3u;
            const uint block_width=nv::max((w>>3u), 2u);
            const uint block_height=nv::max((h>>2u), 2u);
            size = d * block_width * block_height * size_factor;
        }
        else {
            // 4 bpp
            const uint bpp = 4u;
            const uint block_size = 4u * 4u;
            const uint size_factor = (block_size*bpp) >> 3u;
            const uint block_width = max((w>>2u), 2u);
            const uint block_height = max((h>>2u), 2u);
            size = d * block_width * block_height * size_factor;
        }

        if (outputOptions.outputHandler != NULL) {
            outputOptions.outputHandler->writeData(texture.getDataPtr(), I32(size));
        }
    }
void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_data) {



	if (p_msg=="debug_enter") {

		Array msg;
		msg.push_back("get_stack_dump");
		ppeer->put_var(msg);
		ERR_FAIL_COND(p_data.size()!=2);
		bool can_continue=p_data[0];
		String error = p_data[1];
		step->set_disabled(!can_continue);
		next->set_disabled(!can_continue);
		reason->set_text(error);
		reason->set_tooltip(error);
		breaked=true;
		dobreak->set_disabled(true);
		docontinue->set_disabled(false);
		emit_signal("breaked",true,can_continue);
		OS::get_singleton()->move_window_to_foreground();
		tabs->set_current_tab(0);

	} else if (p_msg=="debug_exit") {

		breaked=false;
		step->set_disabled(true);
		next->set_disabled(true);
		reason->set_text("");
		reason->set_tooltip("");
		back->set_disabled(true);
		forward->set_disabled(true);
		dobreak->set_disabled(false);
		docontinue->set_disabled(true);
		emit_signal("breaked",false,false);
		//tabs->set_current_tab(0);

	} else if (p_msg=="message:click_ctrl") {

		clicked_ctrl->set_text(p_data[0]);
		clicked_ctrl_type->set_text(p_data[1]);

	} else if (p_msg=="message:scene_tree") {

		scene_tree->clear();
		Map<int,TreeItem*> lv;

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

			TreeItem *p;
			int level = p_data[i];
			if (level==0) {
				p = NULL;
			} else {
				ERR_CONTINUE(!lv.has(level-1));
				p=lv[level-1];
			}

			TreeItem *it = scene_tree->create_item(p);
			it->set_text(0,p_data[i+1]);
			if (has_icon(p_data[i+2],"EditorIcons"))
				it->set_icon(0,get_icon(p_data[i+2],"EditorIcons"));
			lv[level]=it;
		}

		le_clear->set_disabled(false);
		le_set->set_disabled(false);

	} else if (p_msg=="message:video_mem") {

		vmem_tree->clear();
		TreeItem* root=vmem_tree->create_item();

		int total=0;

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

			TreeItem *it = vmem_tree->create_item(root);
			String type=p_data[i+1];
			int bytes=p_data[i+3].operator int();
			it->set_text(0,p_data[i+0]); //path
			it->set_text(1,type); //type
			it->set_text(2,p_data[i+2]); //type
			it->set_text(3,String::humanize_size(bytes)); //type
			total+=bytes;

			if (has_icon(type,"EditorIcons"))
				it->set_icon(0,get_icon(type,"EditorIcons"));
		}

		vmem_total->set_tooltip("Bytes: "+itos(total));
		vmem_total->set_text(String::humanize_size(total));

	} else if (p_msg=="stack_dump") {

		stack_dump->clear();
		TreeItem *r = stack_dump->create_item();

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

			Dictionary d = p_data[i];
			ERR_CONTINUE(!d.has("function"));
			ERR_CONTINUE(!d.has("file"));
			ERR_CONTINUE(!d.has("line"));
			ERR_CONTINUE(!d.has("id"));
			TreeItem *s = stack_dump->create_item(r);
			d["frame"]=i;
			s->set_metadata(0,d);

//			String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"])+" - at func: "+d["function"];
			String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"]);
			s->set_text(0,line);

			if (i==0)
				s->select(0);
		}
	} else if (p_msg=="stack_frame_vars") {


		variables->clear();



		int ofs =0;
		int mcount = p_data[ofs];

		ofs++;
		for(int i=0;i<mcount;i++) {

			String n = p_data[ofs+i*2+0];
			Variant v = p_data[ofs+i*2+1];

			if (n.begins_with("*")) {

				n=n.substr(1,n.length());
			}

			variables->add_property("members/"+n,v);
		}
		ofs+=mcount*2;

		mcount = p_data[ofs];

		ofs++;
		for(int i=0;i<mcount;i++) {

			String n = p_data[ofs+i*2+0];
			Variant v = p_data[ofs+i*2+1];

			if (n.begins_with("*")) {

				n=n.substr(1,n.length());
			}


			variables->add_property("locals/"+n,v);
		}

		variables->update();
		inspector->edit(variables);

	} else if (p_msg=="output") {

		//OUT
		for(int i=0;i<p_data.size();i++) {

			String t = p_data[i];
			//LOG

			if (EditorNode::get_log()->is_hidden()) {
				log_forced_visible=true;
				EditorNode::get_log()->show();
			}
			EditorNode::get_log()->add_message(t);

		}

	} else if (p_msg=="performance") {
		Array arr = p_data[0];
		Vector<float> p;
		p.resize(arr.size());
		for(int i=0;i<arr.size();i++) {
			p[i]=arr[i];
			if (i<perf_items.size()) {
				perf_items[i]->set_text(1,rtos(p[i]));
				if (p[i]>perf_max[i])
					perf_max[i]=p[i];
			}

		}
		perf_history.push_front(p);
		perf_draw->update();

	} else if (p_msg=="error") {

		Array err = p_data[0];

		Array vals;
		vals.push_back(err[0]);
		vals.push_back(err[1]);
		vals.push_back(err[2]);
		vals.push_back(err[3]);

		bool warning = err[9];
		bool e;
		String time = String("%d:%02d:%02d:%04d").sprintf(vals,&e);
		String txt=time+" - "+String(err[8]);

		String tooltip="Type:"+String(warning?"Warning":"Error");
		tooltip+="\nDescription: "+String(err[8]);
		tooltip+="\nTime: "+time;
		tooltip+="\nC Error: "+String(err[7]);
		tooltip+="\nC Source: "+String(err[5])+":"+String(err[6]);
		tooltip+="\nC Function: "+String(err[4]);



		error_list->add_item(txt,EditorNode::get_singleton()->get_gui_base()->get_icon(warning?"Warning":"Error","EditorIcons"));
		error_list->set_item_tooltip( error_list->get_item_count() -1,tooltip );

		int scc = p_data[1];

		Array stack;
		stack.resize(scc);
		for(int i=0;i<scc;i++) {
			stack[i]=p_data[2+i];
		}

		error_list->set_item_metadata( error_list->get_item_count() -1,stack );

		error_count++;
		/*
		int count = p_data[1];

		Array cstack;

		OutputError oe = errors.front()->get();

		packet_peer_stream->put_var(oe.hr);
		packet_peer_stream->put_var(oe.min);
		packet_peer_stream->put_var(oe.sec);
		packet_peer_stream->put_var(oe.msec);
		packet_peer_stream->put_var(oe.source_func);
		packet_peer_stream->put_var(oe.source_file);
		packet_peer_stream->put_var(oe.source_line);
		packet_peer_stream->put_var(oe.error);
		packet_peer_stream->put_var(oe.error_descr);
		packet_peer_stream->put_var(oe.warning);
		packet_peer_stream->put_var(oe.callstack);
		*/
	} else if (p_msg=="kill_me") {

		editor->call_deferred("stop_child_process");
	}

}
Example #6
0
static bool _guess_expression_type(GDCompletionContext& context,const GDParser::Node* p_node,int p_line,GDCompletionIdentifier &r_type) {


	if (p_node->type==GDParser::Node::TYPE_CONSTANT) {

		const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(p_node);

		r_type=_get_type_from_variant(cn->value);

		return true;
	} else if (p_node->type==GDParser::Node::TYPE_DICTIONARY) {

		r_type.type=Variant::DICTIONARY;


		//what the heck, fill it anyway
		const GDParser::DictionaryNode *an = static_cast<const GDParser::DictionaryNode *>(p_node);
		Dictionary d;
		for(int i=0;i<an->elements.size();i++) {
			GDCompletionIdentifier k;
			if (_guess_expression_type(context,an->elements[i].key,p_line,k) && k.value.get_type()!=Variant::NIL) {
				GDCompletionIdentifier v;
				if (_guess_expression_type(context,an->elements[i].value,p_line,v)) {
					d[k.value]=v.value;
				}

			}
		}
		r_type.value=d;
		return true;
	} else if (p_node->type==GDParser::Node::TYPE_ARRAY) {

		r_type.type=Variant::ARRAY;
		//what the heck, fill it anyway
		const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(p_node);
		Array arr;
		arr.resize(an->elements.size());
		for(int i=0;i<an->elements.size();i++) {
			GDCompletionIdentifier ci;
			if (_guess_expression_type(context,an->elements[i],p_line,ci)) {
				arr[i]=ci.value;
			}
		}
		r_type.value=arr;
		return true;

	} else if (p_node->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) {

		MethodInfo mi = GDFunctions::get_info(static_cast<const GDParser::BuiltInFunctionNode*>(p_node)->function);
		r_type=_get_type_from_pinfo(mi.return_val);

		return true;
	} else if (p_node->type==GDParser::Node::TYPE_IDENTIFIER) {

		return _guess_identifier_type(context,p_line-1,static_cast<const GDParser::IdentifierNode *>(p_node)->name,r_type);
	} else if (p_node->type==GDParser::Node::TYPE_SELF) {
		//eeh...

		r_type=_get_native_class(context);
		return r_type.type!=Variant::NIL;

	} else if (p_node->type==GDParser::Node::TYPE_OPERATOR) {


		const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_node);
		if (op->op==GDParser::OperatorNode::OP_CALL) {
			if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) {

				const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode *>(op->arguments[0]);
				r_type.type=tn->vtype;
				return true;
			} else if (op->arguments[0]->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) {


				const GDParser::BuiltInFunctionNode *bin = static_cast<const GDParser::BuiltInFunctionNode *>(op->arguments[0]);
				return _guess_expression_type(context,bin,p_line,r_type);

			} else if (op->arguments.size()>1 && op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) {


				GDCompletionIdentifier base;
				if (!_guess_expression_type(context,op->arguments[0],p_line,base))
					return false;

				StringName id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1])->name;

				if (base.type==Variant::OBJECT) {

					if (id.operator String()=="new" && base.value.get_type()==Variant::OBJECT) {
						Object *obj = base.value;
						if (obj && obj->cast_to<GDNativeClass>()) {
							GDNativeClass *gdnc = obj->cast_to<GDNativeClass>();
							r_type.type=Variant::OBJECT;
							r_type.value=Variant();
							r_type.obj_type=gdnc->get_name();
							return true;
						}
					}

					if (ObjectTypeDB::has_method(base.obj_type,id)) {

#ifdef TOOLS_ENABLED
						MethodBind *mb = ObjectTypeDB::get_method(base.obj_type,id);
						PropertyInfo pi = mb->get_argument_info(-1);

						//try calling the function if constant and all args are constant, should not crash..
						Object *baseptr = base.value;

						if (baseptr && mb->is_const() && pi.type==Variant::OBJECT) {
							bool all_valid=true;
							Vector<Variant> args;
							for(int i=2;i<op->arguments.size();i++) {
								GDCompletionIdentifier arg;

								if (_guess_expression_type(context,op->arguments[i],p_line,arg)) {
									if (arg.value.get_type()!=Variant::NIL && arg.value.get_type()!=Variant::OBJECT) { // calling with object seems dangerous, i don' t know
										args.push_back(arg.value);
									} else {
										all_valid=false;
										break;
									}
								} else {
									all_valid=false;
								}
							}
							if (all_valid) {
								Vector<const Variant*> argptr;
								for(int i=0;i<args.size();i++) {
									argptr.push_back(&args[i]);
								}

								Variant::CallError ce;
								Variant ret=mb->call(baseptr,argptr.ptr(),argptr.size(),ce);


								if (ce.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) {

									if (ret.get_type()!=Variant::OBJECT || ret.operator Object*()!=NULL) {

										r_type=_get_type_from_variant(ret);
										return true;
									}
								}

							}
						}

						r_type.type=pi.type;
						if (pi.hint==PROPERTY_HINT_RESOURCE_TYPE) {
							r_type.obj_type=pi.hint_string;
						}



						return true;
#else
						return false;
#endif
					} else {
						return false;
					}
				} else {
					//method for some variant..
					Variant::CallError ce;
					Variant v = Variant::construct(base.type,NULL,0,ce);
					List<MethodInfo> mi;
					v.get_method_list(&mi);
					for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) {

						if (!E->get().name.begins_with("_") && E->get().name==id.operator String()) {


							MethodInfo mi = E->get();
							r_type.type=mi.return_val.type;
							if (mi.return_val.hint==PROPERTY_HINT_RESOURCE_TYPE) {
								r_type.obj_type=mi.return_val.hint_string;
							}
							return true;
						}
					}

				}


			}
		} else if (op->op==GDParser::OperatorNode::OP_INDEX || op->op==GDParser::OperatorNode::OP_INDEX_NAMED) {

			GDCompletionIdentifier p1;
			GDCompletionIdentifier p2;



			if (op->op==GDParser::OperatorNode::OP_INDEX_NAMED) {

				if (op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) {
					String id = static_cast<const GDParser::IdentifierNode*>(op->arguments[1])->name;
					p2.type=Variant::STRING;
					p2.value=id;
				}

			} else {
				if (op->arguments[1]) {
					if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) {

						return false;
					}
				}
			}

			if (op->arguments[0]->type==GDParser::Node::TYPE_ARRAY) {

				const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(op->arguments[0]);
				if (p2.value.is_num()) {
					int index = p2.value;
					if (index<0 || index>=an->elements.size())
						return false;
					return _guess_expression_type(context,an->elements[index],p_line,r_type);
				}

			} else if (op->arguments[0]->type==GDParser::Node::TYPE_DICTIONARY) {

				const GDParser::DictionaryNode *dn = static_cast<const GDParser::DictionaryNode *>(op->arguments[0]);

				if (p2.value.get_type()==Variant::NIL)
					return false;

				for(int i=0;i<dn->elements.size();i++) {

					GDCompletionIdentifier k;

					if (!_guess_expression_type(context,dn->elements[i].key,p_line,k)) {

						return false;
					}

					if (k.value.get_type()==Variant::NIL)
						return false;

					if (k.value==p2.value) {

						return _guess_expression_type(context,dn->elements[i].value,p_line,r_type);
					}
				}

			} else {

				if (op->arguments[0]) {
					if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) {

						return false;
					}

				}

				if (p1.value.get_type()==Variant::OBJECT) {
					//??
				} else if (p1.value.get_type()!=Variant::NIL) {

					bool valid;
					Variant ret = p1.value.get(p2.value,&valid);
					if (valid) {
						r_type=_get_type_from_variant(ret);
						return true;
					}

				} else {
					if (p1.type!=Variant::NIL) {
						Variant::CallError ce;
						Variant base = Variant::construct(p1.type,NULL,0,ce);
						bool valid;
						Variant ret = base.get(p2.value,&valid);
						if (valid) {
							r_type=_get_type_from_variant(ret);
							return true;
						}
					}
				}
			}

		} else {


			Variant::Operator vop = Variant::OP_MAX;
			switch(op->op) {
				case GDParser::OperatorNode::OP_ADD: vop=Variant::OP_ADD; break;
				case GDParser::OperatorNode::OP_SUB: vop=Variant::OP_SUBSTRACT; break;
				case GDParser::OperatorNode::OP_MUL: vop=Variant::OP_MULTIPLY; break;
				case GDParser::OperatorNode::OP_DIV: vop=Variant::OP_DIVIDE; break;
				case GDParser::OperatorNode::OP_MOD: vop=Variant::OP_MODULE; break;
				case GDParser::OperatorNode::OP_SHIFT_LEFT: vop=Variant::OP_SHIFT_LEFT; break;
				case GDParser::OperatorNode::OP_SHIFT_RIGHT: vop=Variant::OP_SHIFT_RIGHT; break;
				case GDParser::OperatorNode::OP_BIT_AND: vop=Variant::OP_BIT_AND; break;
				case GDParser::OperatorNode::OP_BIT_OR: vop=Variant::OP_BIT_OR; break;
				case GDParser::OperatorNode::OP_BIT_XOR: vop=Variant::OP_BIT_XOR; break;
				default:{}

			}



			if (vop==Variant::OP_MAX)
				return false;



			GDCompletionIdentifier p1;
			GDCompletionIdentifier p2;

			if (op->arguments[0]) {
				if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) {

					return false;
				}

			}

			if (op->arguments.size()>1) {
				if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) {

					return false;
				}
			}

			Variant::CallError ce;
			bool v1_use_value = p1.value.get_type()!=Variant::NIL && p1.value.get_type()!=Variant::OBJECT;
			Variant v1 = (v1_use_value)?p1.value:Variant::construct(p1.type,NULL,0,ce);
			bool v2_use_value = p2.value.get_type()!=Variant::NIL && p2.value.get_type()!=Variant::OBJECT;
			Variant v2 = (v2_use_value)?p2.value:Variant::construct(p2.type,NULL,0,ce);
			// avoid potential invalid ops
			if ((vop==Variant::OP_DIVIDE || vop==Variant::OP_MODULE) && v2.get_type()==Variant::INT) {
				v2=1;
				v2_use_value=false;
			}
			if (vop==Variant::OP_DIVIDE && v2.get_type()==Variant::REAL) {
				v2=1.0;
				v2_use_value=false;
			}

			Variant r;
			bool valid;
			Variant::evaluate(vop,v1,v2,r,valid);
			if (!valid)
				return false;
			r_type.type=r.get_type();
			if (v1_use_value && v2_use_value)
				r_type.value=r;

			return true;

		}

	}

	return false;
}
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);

}