Esempio n. 1
0
		const lib::vector2ds32 negatedDirectionVector(const lib::u32 scale = 1) const
		{
			lib::vector2ds32 result{ directionVector(scale) };
			result *= (lib::s32) - 1;
			return result;
		}
Esempio n. 2
0
    float scoreForWidget(GuiWidget const &widget, ui::Direction dir) const
    {
        if (!widget.canBeFocused() || &widget == thisPublic)
        {
            return -1;
        }

        Rectanglef const viewRect  = self().root().viewRule().rect();
        Rectanglef const selfRect  = self().hitRule().rect();
        Rectanglef const otherRect = widget.hitRule().rect();
        Vector2f const otherMiddle =
                (dir == ui::Up?   otherRect.midBottom() :
                 dir == ui::Down? otherRect.midTop()    :
                 dir == ui::Left? otherRect.midRight()  :
                                  otherRect.midLeft()  );
                //otherRect.middle();

        if (!viewRect.contains(otherMiddle))
        {
            return -1;
        }

        bool const axisOverlap =
                (isHorizontal(dir) && !selfRect.vertical()  .intersection(otherRect.vertical())  .isEmpty()) ||
                (isVertical(dir)   && !selfRect.horizontal().intersection(otherRect.horizontal()).isEmpty());

        // Check for contacting edges.
        float edgeDistance = 0; // valid only if axisOverlap
        if (axisOverlap)
        {
            switch (dir)
            {
            case ui::Left:
                edgeDistance = selfRect.left() - otherRect.right();
                break;

            case ui::Up:
                edgeDistance = selfRect.top() - otherRect.bottom();
                break;

            case ui::Right:
                edgeDistance = otherRect.left() - selfRect.right();
                break;

            default:
                edgeDistance = otherRect.top() - selfRect.bottom();
                break;
            }
            // Very close edges are considered contacting.
            if (edgeDistance >= 0 && edgeDistance < toDevicePixels(5))
            {
                return edgeDistance;
            }
        }

        Vector2f const middle    = (dir == ui::Up?   selfRect.midTop()    :
                                    dir == ui::Down? selfRect.midBottom() :
                                    dir == ui::Left? selfRect.midLeft()   :
                                                     selfRect.midRight() );
        Vector2f const delta     = otherMiddle - middle;
        Vector2f const dirVector = directionVector(dir);
        auto dotProd = delta.normalize().dot(dirVector);
        if (dotProd <= 0)
        {
            // On the wrong side.
            return -1;
        }
        float distance = delta.length();
        if (axisOverlap)
        {
            dotProd = 1.0;
            if (edgeDistance > 0)
            {
                distance = de::min(distance, edgeDistance);
            }
        }

        float favorability = 1;
        if (widget.parentWidget() == self().parentWidget())
        {
            favorability = .1f; // Siblings are much preferred.
        }
        else if (self().hasAncestor(widget) || widget.hasAncestor(self()))
        {
            favorability = .2f; // Ancestry is also good.
        }

        // Prefer widgets that are nearby, particularly in the specified direction.
        return distance * (.5f + acos(dotProd)) * favorability;
    }
Esempio n. 3
0
		lib::vector2du32 applyToVector(const lib::vector2du32 &v,const lib::u32 scale = 1) const
		{
			lib::vector2ds32 dv{ directionVector(scale) };
			lib::vector2du32 result(v.x + dv.x, v.y + dv.y);
			return result;
		}
Esempio n. 4
0
MStatus sweptEmitter::compute(const MPlug& plug, MDataBlock& block)
//
//	Descriptions:
//		Call emit emit method to generate new particles.
//
{
	MStatus status;

	// Determine if we are requesting the output plug for this emitter node.
	//
	if( !(plug == mOutput) )
        return( MS::kUnknownParameter );

	// Get the logical index of the element this plug refers to,
	// because the node can be emitting particles into more 
    // than one particle shape.
	//
	int multiIndex = plug.logicalIndex( &status );
	McheckErr(status, "ERROR in plug.logicalIndex.\n");

	// Get output data arrays (position, velocity, or parentId)
	// that the particle shape is holding from the previous frame.
	//
	MArrayDataHandle hOutArray = block.outputArrayValue(mOutput, &status);
	McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n");

	// Create a builder to aid in the array construction efficiently.
	//
	MArrayDataBuilder bOutArray = hOutArray.builder( &status );
	McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n");

	// Get the appropriate data array that is being currently evaluated.
	//
	MDataHandle hOut = bOutArray.addElement(multiIndex, &status);
	McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n");

    // Get the data and apply the function set.
    //
    MFnArrayAttrsData fnOutput;
    MObject dOutput = fnOutput.create ( &status );
    McheckErr(status, "ERROR in fnOutput.create.\n");

	// Check if the particle object has reached it's maximum,
	// hence is full. If it is full then just return with zero particles.
	//
	bool beenFull = isFullValue( multiIndex, block );
	if( beenFull )
	{
		return( MS::kSuccess );
	}

	// Get deltaTime, currentTime and startTime.
	// If deltaTime <= 0.0, or currentTime <= startTime,
	// do not emit new pariticles and return.
	//
	MTime cT = currentTimeValue( block );
	MTime sT = startTimeValue( multiIndex, block );
	MTime dT = deltaTimeValue( multiIndex, block );
	if( (cT <= sT) || (dT <= 0.0) )
	{
		// We do not emit particles before the start time, 
		// and do not emit particles when moving backwards in time.
		// 

		// This code is necessary primarily the first time to 
		// establish the new data arrays allocated, and since we have 
		// already set the data array to length zero it does 
		// not generate any new particles.
		// 
		hOut.set( dOutput );
		block.setClean( plug );

		return( MS::kSuccess );
	}

	// Get speed, direction vector, and inheritFactor attributes.
	//
	double speed = speedValue( block );
	MVector dirV = directionVector( block );
	double inheritFactor = inheritFactorValue( multiIndex, block );

	// Get the position and velocity arrays to append new particle data.
	//
	MVectorArray fnOutPos = fnOutput.vectorArray("position", &status);
	MVectorArray fnOutVel = fnOutput.vectorArray("velocity", &status);

	// Convert deltaTime into seconds.
	//
	double dt = dT.as( MTime::kSeconds );
	
	// Apply rotation to the direction vector
	MVector rotatedV = useRotation ( dirV );


	// position,
	MVectorArray inPosAry;
	// velocity
	MVectorArray inVelAry;
	// emission rate
	MIntArray emitCountPP;


	// Get the swept geometry data
	//
	MObject thisObj = this->thisMObject();
	MPlug sweptPlug( thisObj, mSweptGeometry );

	if ( sweptPlug.isConnected() ) 
	{
		MDataHandle sweptHandle = block.inputValue( mSweptGeometry );
		// MObject sweptData = sweptHandle.asSweptGeometry();
		MObject sweptData = sweptHandle.data();
		MFnDynSweptGeometryData fnSweptData( sweptData );


		// Curve emission
		//
		if (fnSweptData.lineCount() > 0) {
			int numLines = fnSweptData.lineCount();
		
			for ( int i=0; i<numLines; i++ )
			{
				inPosAry.clear();
				inVelAry.clear();
				emitCountPP.clear();

				MDynSweptLine line = fnSweptData.sweptLine( i );

				// ... process current line ...
				MVector p1 = line.vertex( 0 );
				MVector p2 = line.vertex( 1 );

				inPosAry.append( p1 );
				inPosAry.append( p2 );

				inVelAry.append( MVector( 0,0,0 ) );
				inVelAry.append( MVector( 0,0,0 ) );

				// emit Rate for two points on line
				emitCountPP.clear();
				status = emitCountPerPoint( plug, block, 2, emitCountPP );

				emit( inPosAry, inVelAry, emitCountPP,
					dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel );

			}
		}

		// Surface emission (nurb or polygon)
		//
		if (fnSweptData.triangleCount() > 0) {
			int numTriangles = fnSweptData.triangleCount();
		
			for ( int i=0; i<numTriangles; i++ )
			{
				inPosAry.clear();
				inVelAry.clear();
				emitCountPP.clear();

				MDynSweptTriangle tri = fnSweptData.sweptTriangle( i );

				// ... process current triangle ...
				MVector p1 = tri.vertex( 0 );
				MVector p2 = tri.vertex( 1 );
				MVector p3 = tri.vertex( 2 );

				MVector center = p1 + p2 + p3;
				center /= 3.0;

				inPosAry.append( center );

				inVelAry.append( MVector( 0,0,0 ) );

				// emit Rate for two points on line
				emitCountPP.clear();
				status = emitCountPerPoint( plug, block, 1, emitCountPP );

				emit( inPosAry, inVelAry, emitCountPP,
					dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel );

			}
		}
	}

	// Update the data block with new dOutput and set plug clean.
	//
	hOut.set( dOutput );
	block.setClean( plug );

	return( MS::kSuccess );
}