コード例 #1
0
ファイル: Animatable.cpp プロジェクト: dreamsxin/Urho3D
void Animatable::SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed)
{
    String outName;
    Animatable* target = FindAttributeAnimationTarget(name, outName);
    if (target)
        target->SetAttributeAnimation(outName, attributeAnimation, wrapMode, speed);
}
コード例 #2
0
ファイル: Animatable.cpp プロジェクト: ViteFalcon/Urho3D
void AttributeAnimationInfo::ApplyValue(const Variant& newValue)
{
    Animatable* animatable = static_cast<Animatable*>(target_.Get());
    if (animatable)
    {
        animatable->OnSetAttribute(attributeInfo_, newValue);
        animatable->ApplyAttributes();
    }
}
コード例 #3
0
bool OrientConstRotation::SvCanConcludeLink(IGraphObjectManager *gom, IGraphNode *gNode, IGraphNode *gNodeChild)
{
	if(GetLocked()==false)
	{
		Animatable *pChildAnim = gNodeChild->GetAnim();
		if( pChildAnim->SuperClassID() == BASENODE_CLASS_ID )
			return true;

		return Control::SvCanConcludeLink(gom, gNode, gNodeChild);
	}
	return false;
}
コード例 #4
0
ファイル: animationengine.cpp プロジェクト: NortySpock/cppVis
  void _AnimationEngine::drawAnim( Animatable& animator )
  {
    int c = 0;
    for
      (
      std::list<SmartPointer<Anim> >::iterator i = animator.getFrames().begin();
      i != animator.getFrames().end();
      i++
      )
    {
      (*i)->animate( TimeManager->getTurnPercent(), animator.getData(), m_currentGame );
    }

  } // _AnimationEngine::drawAnim()
コード例 #5
0
bool OrientConstRotation::SvLinkChild(IGraphObjectManager *gom, IGraphNode *gNodeThis, IGraphNode *gNodeChild)
{
	if(GetLocked()==false)
	{
		Animatable *pChildAnim = gNodeChild->GetAnim();
		if( pChildAnim->SuperClassID() == BASENODE_CLASS_ID ) {
			if( AppendTarget( (INode*)pChildAnim ) ) {
				NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
				GetCOREInterface()->RedrawViews(GetCOREInterface()->GetTime());
				return true;
			}
		}
		return Control::SvLinkChild(gom, gNodeThis, gNodeChild);
	}
	return false;
}
コード例 #6
0
ファイル: appdata.cpp プロジェクト: artemeliy/inf4715
void AppDataTest::PutAppData()
	{
	Animatable *anim = PickAnim();
	if (!anim) return;

	// XRef stuff 020416  --prs.
	if (s_through_xref) {
		RefTargetHandle rth = (RefTargetHandle)anim;
		IXRefItem* xi = NULL;
		while (rth != NULL && (xi = IXRefItem::GetInterface(*rth)) != NULL)
			rth = xi->GetSrcItem();
		if (rth != NULL)
			anim = rth;
	}

	// Load the text out of the edit field into a buffer
	int text_len = GetWindowTextLength(GetDlgItem(hPanel,IDC_APPDATA_EDIT))+1;
	TSTR theText;
	theText.Resize(text_len);
	GetWindowText(
		GetDlgItem(hPanel,IDC_APPDATA_EDIT),
		theText.dataForWrite(), text_len);

	MaxSDK::Util::MaxString m_string;
	theText.ToMaxString(m_string);
	const char* a_string = m_string.ToUTF8();
	size_t len = strlen(a_string)+4; // 3 for UTF8 BOM, one for null
	char* buf = (char*)MAX_malloc(len);
	strcpy(buf, "\xef\xbb\xbf"); // UTF8 BOM
	strcat(buf, a_string);

	// Remove the chunk if it exists
	anim->RemoveAppDataChunk(
		APPDATA_TEST_CLASS_ID, 
		UTILITY_CLASS_ID, 
		spin->GetIVal());

	// Add a chunk
	anim->AddAppDataChunk(
		APPDATA_TEST_CLASS_ID, 
		UTILITY_CLASS_ID, 
		spin->GetIVal(),
		(DWORD)len, buf);
	}
コード例 #7
0
ファイル: appdata.cpp プロジェクト: artemeliy/inf4715
void AppDataTest::GetAppData()
	{
	Animatable *anim = PickAnim();
	if (!anim) return;

	// XRef stuff 020416  --prs.
	if (s_through_xref) {
		RefTargetHandle rth = (RefTargetHandle)anim;
		IXRefItem* xi = NULL;
		while (rth != NULL && (xi = IXRefItem::GetInterface(*rth)) != NULL)
			rth = xi->GetSrcItem();
		if (rth != NULL)
			anim = rth;
	}

	// Grab the app data chunk from the anim
	AppDataChunk *ad = 
		anim->GetAppDataChunk(
			APPDATA_TEST_CLASS_ID, 
			UTILITY_CLASS_ID, 
			spin->GetIVal());
	if (ad && ad->data) {
		// Fill the edit field with the text.
		TSTR data;
		const char* raw_string = (const char*)ad->data;
		if (strncmp(raw_string, "\xef\xbb\xbf", 3) == 0)
			data = TSTR::FromUTF8(raw_string+3);
		else
		{
			DbgAssert(!_T("Should always convert appdata in UpdateAppDataLoadProc"));
			Interface14 *iface = GetCOREInterface14();
			LANGID langID = iface->LanguageToUseForFileIO();
			UINT codePage = iface->CodePageForLanguage(langID);
			data = TSTR::FromCP(codePage, raw_string);
		}
		SetDlgItemText(hPanel,IDC_APPDATA_EDIT,data.data());
	} else {
		// Not found!
		MessageBox(hPanel,_T("No app data found"),_T("App Data Tester"),MB_OK);
		}
	}
コード例 #8
0
ファイル: Animatable.cpp プロジェクト: dreamsxin/Urho3D
void Animatable::SetAnimationTime(float time)
{
    if (objectAnimation_)
    {
        // In object animation there may be targets in hierarchy. Set same time in all
        const HashMap<String, SharedPtr<ValueAnimationInfo> >& infos = objectAnimation_->GetAttributeAnimationInfos();
        for (HashMap<String, SharedPtr<ValueAnimationInfo> >::ConstIterator i = infos.Begin(); i != infos.End(); ++i)
        {
            String outName;
            Animatable* target = FindAttributeAnimationTarget(i->first_, outName);
            if (target)
                target->SetAttributeAnimationTime(outName, time);
        }
    }
    else
    {
        for (HashMap<String, SharedPtr<AttributeAnimationInfo> >::ConstIterator i = attributeAnimationInfos_.Begin();
            i != attributeAnimationInfos_.End(); ++i)
            i->second_->SetTime(time);
    }
}
コード例 #9
0
bool assignController(Animatable* controller, Animatable* pObj, int i, int j,
                      int k = -1)
{
    if (i >= pObj->NumSubs()) {
        return false;
    }

    Animatable* an = pObj->SubAnim(i);

    if (!an || j >= an->NumSubs()) {
        return false;
    }
    int aIndex = j;

    if (k != -1) {
        an = an->SubAnim(j);
        if (k >= an->NumSubs()) {
            return false;
        }
        aIndex = k;
    }

    return an->AssignController(controller, aIndex) == TRUE;
}
コード例 #10
0
ファイル: BT_AnimationManager.cpp プロジェクト: DX94/BumpTop
// This function calls any function that should be called when this animation finishes
void AnimationManager::finishedAnimation(AnimationEntry entry)
{
	FinishedCallBack fnCb = entry.getCallback();
	AnimationEntry tempEntry(entry.getObject(), entry.getCallback(), entry.getCustomData());
	Animatable *obj = entry.getObject();

	// Kill off the entry so there are no dangling pointers
	removeAnimation(entry.getObject());

	if (obj)
	{
		// ALow the object to finish properly
		obj->onAnimFinished();
	}	

	if (fnCb)
	{
		// Finish this animation by calling the callback function specified
		fnCb(tempEntry);
	}

	textManager->invalidate();
	rndrManager->invalidateRenderer();
}
コード例 #11
0
AlembicFloatController* getController(Animatable* pObj,
                                      const std::string& identifier,
                                      const std::string& camProperty, int i,
                                      int j, int k = -1)
{
    if (i >= pObj->NumSubs()) {
        return NULL;
    }

    Animatable* an = pObj->SubAnim(i);

    if (!an || j >= an->NumSubs()) {
        return NULL;
    }

    an = an->SubAnim(j);

    if (k != -1) {
        if (!an || k >= an->NumSubs()) {
            return NULL;
        }
        an = an->SubAnim(k);
    }

    Class_ID cid = an->ClassID();
    if (!an || an->ClassID() != ALEMBIC_FLOAT_CONTROLLER_CLASSID) {
        return NULL;
    }

    AlembicFloatController* pControl = static_cast<AlembicFloatController*>(an);
    TimeValue zero(0);
    std::string contIdentifier =
        EC_MCHAR_to_UTF8(pControl->GetParamBlockByID(0)->GetStr(
                             GetParamIdByName(pControl, 0, "identifier"), zero));
    if (strcmp(contIdentifier.c_str(), identifier.c_str()) != 0) {
        return NULL;
    }

    std::string contCamProperty =
        EC_MCHAR_to_UTF8(pControl->GetParamBlockByID(0)->GetStr(
                             GetParamIdByName(pControl, 0, "property"), zero));
    if (strcmp(contCamProperty.c_str(), camProperty.c_str()) != 0) {
        return NULL;
    }

    return pControl;
}
コード例 #12
0
static bool
SampleAnimations(Layer* aLayer, TimeStamp aPoint)
{
  AnimationArray& animations = aLayer->GetAnimations();
  InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();

  bool activeAnimations = false;

  for (uint32_t i = animations.Length(); i-- !=0; ) {
    Animation& animation = animations[i];
    AnimData& animData = animationData[i];

    double numIterations = animation.numIterations() != -1 ?
      animation.numIterations() : NS_IEEEPositiveInfinity();
    double positionInIteration =
      ElementAnimations::GetPositionInIteration(aPoint - animation.startTime(),
                                                animation.duration(),
                                                numIterations,
                                                animation.direction());

    NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
                      positionInIteration <= 1.0,
                      "position should be in [0-1]");

    int segmentIndex = 0;
    AnimationSegment* segment = animation.segments().Elements();
    while (segment->endPortion() < positionInIteration) {
      ++segment;
      ++segmentIndex;
    }

    double positionInSegment = (positionInIteration - segment->startPortion()) /
                                 (segment->endPortion() - segment->startPortion());

    double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment);

    activeAnimations = true;

    // interpolate the property
    Animatable interpolatedValue;
    SampleValue(portion, animation, animData.mStartValues[segmentIndex],
                animData.mEndValues[segmentIndex], &interpolatedValue);
    LayerComposite* layerComposite = aLayer->AsLayerComposite();
    switch (animation.property()) {
    case eCSSProperty_opacity:
    {
      layerComposite->SetShadowOpacity(interpolatedValue.get_float());
      break;
    }
    case eCSSProperty_transform:
    {
      gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
      if (ContainerLayer* c = aLayer->AsContainerLayer()) {
        matrix.ScalePost(c->GetInheritedXScale(),
                         c->GetInheritedYScale(),
                         1);
      }
      layerComposite->SetShadowTransform(matrix);
      layerComposite->SetShadowTransformSetByAnimation(true);
      break;
    }
    default:
      NS_WARNING("Unhandled animated property");
    }
  }

  for (Layer* child = aLayer->GetFirstChild(); child;
       child = child->GetNextSibling()) {
    activeAnimations |= SampleAnimations(child, aPoint);
  }

  return activeAnimations;
}
コード例 #13
0
///////////////////////////////////////////////////////////////////////////////////////////////////
// AlembicImport_vis
///////////////////////////////////////////////////////////////////////////////////////////////////
void AlembicImport_SetupVisControl(std::string const &file,
                                   std::string const &identifier,
                                   AbcG::IObject &obj, INode *pNode,
                                   alembic_importoptions &options)
{
  if (!pNode) {
    return;
  }

  AbcG::IVisibilityProperty visibilityProperty = getAbcVisibilityProperty(obj);

  bool isConstant = true;
  if (visibilityProperty.valid()) {
    isConstant = visibilityProperty.isConstant();
  }

  if (isConstant) {
    Animatable *pAnimatable = pNode->SubAnim(0);

    if (pAnimatable &&
        pAnimatable->ClassID() == ALEMBIC_VISIBILITY_CONTROLLER_CLASSID) {
      pNode->DeleteSubAnim(0);
    }

    alembic_fillvis_options visFillOptions;
    visFillOptions.pIObj = &obj;
    visFillOptions.dTicks = 0;
    visFillOptions.bOldVisibility = true;
    AlembicImport_FillInVis(visFillOptions);
    BOOL bVis = visFillOptions.bVisibility ? TRUE : FALSE;
    float fBool = bVis ? 1.0f : 0.0f;
    pNode->SetVisibility(0, fBool);
  }
  else {
    // Create the xform modifier
    AlembicVisibilityController *pControl =
        static_cast<AlembicVisibilityController *>(
            GetCOREInterface()->CreateInstance(
                CTRL_FLOAT_CLASS_ID, ALEMBIC_VISIBILITY_CONTROLLER_CLASSID));

    // Set the alembic id
    TimeValue t = GET_MAX_INTERFACE()->GetTime();

    TimeValue zero(0);

    // Set the alembic id
    pControl->GetParamBlockByID(0)->SetValue(
        GetParamIdByName(pControl, 0, "path"), zero,
        EC_UTF8_to_TCHAR(file.c_str()));
    pControl->GetParamBlockByID(0)->SetValue(
        GetParamIdByName(pControl, 0, "identifier"), zero,
        EC_UTF8_to_TCHAR(identifier.c_str()));
    pControl->GetParamBlockByID(0)->SetValue(
        GetParamIdByName(pControl, 0, "time"), zero, 0.0f);
    pControl->GetParamBlockByID(0)->SetValue(
        GetParamIdByName(pControl, 0, "muted"), zero, FALSE);

    // Add the modifier to the node
    pNode->SetVisController(pControl);

    if (!isConstant) {
      std::stringstream controllerName;
      controllerName << GET_MAXSCRIPT_NODE(pNode);
      controllerName << "mynode2113.visibility.controller.time";
      AlembicImport_ConnectTimeControl(controllerName.str().c_str(), options);
    }
  }
}
コード例 #14
0
bool HoudiniEngineMesh::UpdateParameters(TimeValue t)
{
	bool need_cook = false;
	if ( assetId >= 0 )
	{
		hapi::Asset asset(assetId);
		if (asset.isValid())
		{
			INode* node = this->GetINode();
			if (node)
			{
				MSTR pname;
				int subs = node->NumSubs();
				for (int i = 0; i < subs; ++i)
				{
					pname = node->SubAnimName(i);
					Animatable* anim = node->SubAnim(i);
					if (anim)
					{
						int blocks = anim->NumParamBlocks();
						for (int block = 0; block < blocks; ++block)
						{
							IParamBlock2 *pblock = anim->GetParamBlock(block);
							if (pblock) {
								TSTR pbname = pblock->GetLocalName();
								int nNumParams = pblock->NumParams();
								ParamID id;
								std::map<std::string, hapi::Parm> params = asset.parmMap();
								for (int i = 0; i < nNumParams; i++)
								{
									id = pblock->IndextoID(i);
									MSTR pname = pblock->GetLocalName(id);
									std::string hname = CStr::FromMSTR(pblock->GetLocalName(id)).data();

									int index = (int)(hname[hname.size() - 1] - '0');
									hname.pop_back();

									if (std::string("__he_input") == hname)
									{
										// input node
										INode* inputnode = pblock->GetINode(id, t);
										if (inputnode)
										{
											need_cook = SetInputNode(index, inputnode) || need_cook;
										}
									}
									else
									{
										// parameters
										if (params.find(hname) != params.end())
										{
											hapi::Parm parm = params[hname];
											if (HAPI_ParmInfo_IsInt(&parm.info()))
											{
												int value = pblock->GetInt(id, t);
												if (value != parm.getIntValue(index))
												{
													parm.setIntValue(index, value);
													need_cook = true;
												}
											}
											else if (HAPI_ParmInfo_IsFloat(&parm.info()))
											{
												float value = pblock->GetFloat(id, t);
												if (value != parm.getFloatValue(index))
												{
													parm.setFloatValue(index, value);
													need_cook = true;
												}
											}
											else if (HAPI_ParmInfo_IsString(&parm.info()))
											{
												std::string value = CStr::FromMSTR(pblock->GetStr(id, t));
												if (value != parm.getStringValue(index))
												{
													parm.setStringValue(index, value.c_str());
													need_cook = true;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return need_cook;
}
コード例 #15
0
static bool
SampleAnimations(Layer* aLayer, TimeStamp aPoint)
{
  AnimationArray& animations = aLayer->GetAnimations();
  InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();

  bool activeAnimations = false;

  for (uint32_t i = animations.Length(); i-- !=0; ) {
    Animation& animation = animations[i];
    AnimData& animData = animationData[i];

    activeAnimations = true;

    TimeDuration elapsedDuration = aPoint - animation.startTime();
    // Skip animations that are yet to start.
    //
    // Currently, this should only happen when the refresh driver is under test
    // control and is made to produce a time in the past or is restored from
    // test control causing it to jump backwards in time.
    //
    // Since activeAnimations is true, this could mean we keep compositing
    // unnecessarily during the delay, but so long as this only happens while
    // the refresh driver is under test control that should be ok.
    if (elapsedDuration.ToSeconds() < 0) {
      continue;
    }

    AnimationTiming timing;
    timing.mIterationDuration = animation.duration();
    // Currently animations run on the compositor have their delay factored
    // into their start time, hence the delay is effectively zero.
    timing.mDelay = TimeDuration(0);
    timing.mIterationCount = animation.iterationCount();
    timing.mDirection = animation.direction();
    // Animations typically only run on the compositor during their active
    // interval but if we end up sampling them outside that range (for
    // example, while they are waiting to be removed) we currently just
    // assume that we should fill.
    timing.mFillMode = NS_STYLE_ANIMATION_FILL_MODE_BOTH;

    ComputedTiming computedTiming =
      dom::Animation::GetComputedTimingAt(
        Nullable<TimeDuration>(elapsedDuration), timing);

    NS_ABORT_IF_FALSE(0.0 <= computedTiming.mTimeFraction &&
                      computedTiming.mTimeFraction <= 1.0,
                      "time fraction should be in [0-1]");

    int segmentIndex = 0;
    AnimationSegment* segment = animation.segments().Elements();
    while (segment->endPortion() < computedTiming.mTimeFraction) {
      ++segment;
      ++segmentIndex;
    }

    double positionInSegment =
      (computedTiming.mTimeFraction - segment->startPortion()) /
      (segment->endPortion() - segment->startPortion());

    double portion =
      animData.mFunctions[segmentIndex]->GetValue(positionInSegment);

    // interpolate the property
    Animatable interpolatedValue;
    SampleValue(portion, animation, animData.mStartValues[segmentIndex],
                animData.mEndValues[segmentIndex], &interpolatedValue);
    LayerComposite* layerComposite = aLayer->AsLayerComposite();
    switch (animation.property()) {
    case eCSSProperty_opacity:
    {
      layerComposite->SetShadowOpacity(interpolatedValue.get_float());
      break;
    }
    case eCSSProperty_transform:
    {
      Matrix4x4 matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
      if (ContainerLayer* c = aLayer->AsContainerLayer()) {
        matrix = matrix * Matrix4x4().Scale(c->GetInheritedXScale(),
                                            c->GetInheritedYScale(),
                                            1);
      }
      layerComposite->SetShadowTransform(matrix);
      layerComposite->SetShadowTransformSetByAnimation(true);
      break;
    }
    default:
      NS_WARNING("Unhandled animated property");
    }
  }

  for (Layer* child = aLayer->GetFirstChild(); child;
       child = child->GetNextSibling()) {
    activeAnimations |= SampleAnimations(child, aPoint);
  }

  return activeAnimations;
}
コード例 #16
0
ファイル: randkeys.cpp プロジェクト: DimondTheCat/xray
void RandKeysUtil::Apply()
	{
	BOOL timeMode   = iu->GetMajorMode()==TVMODE_EDITTIME;
	BOOL fcurveMode = iu->GetMajorMode()==TVMODE_EDITFCURVE;
	Interval iv = iu->GetTimeSelection();
	if (!doTime && !doVal) return;

	theHold.Begin();

	// Turn animation on
	SuspendAnimate();
	AnimateOn();

	for (int i=0; i<iu->GetNumTracks(); i++) {
		if ((timeMode||fcurveMode) && !iu->IsSelected(i)) continue;
		
		// Get Interfaces
		Animatable *anim   = iu->GetAnim(i);
		Animatable *client = iu->GetClient(i);
		int subNum         = iu->GetSubNum(i);
		Control *cont      = GetControlInterface(anim);
		IKeyControl *ikc   = GetKeyControlInterface(anim);
		IKey *key          = GetKeyPointer(anim->SuperClassID(),anim->ClassID());				
		if (!ikc || !cont || !key) continue;						
		if (fcurveMode && !anim->IsCurveSelected()) continue;

		// Get the param dim
		float min = negVal, max = posVal;
		ParamDimension *dim = client->GetParamDimension(subNum);
		if (dim) {
			min = dim->UnConvert(min);
			max = dim->UnConvert(max);
			}

		for (int j=0; j<ikc->GetNumKeys(); j++) {
			// Get the key data
			ikc->GetKey(j,key);
			
			// Check if it's selected
			if (timeMode && !iv.InInterval(key->time)) continue;
			if (!timeMode && !(key->flags&IKEY_SELECTED)) continue;			

			// Randomize time
			if (doTime) {
				key->time = (int)CompRand(
					float(key->time-negTime),
					float(key->time+posTime));
				ikc->SetKey(j,key);
				}
			}

		if (doTime) ikc->SortKeys();

		for (j=0; j<ikc->GetNumKeys(); j++) {
			// Get the key data
			ikc->GetKey(j,key);
			
			// Check if it's selected
			if (timeMode && !iv.InInterval(key->time)) continue;
			if (!timeMode && !(key->flags&IKEY_SELECTED)) continue;			

			// Randomize value
			if (doVal) {
				Point3 pt, ang;
				Point4 p4;
				float f;
				Quat q;
				ScaleValue s;				
				BOOL doX, doY, doZ, doW;
				doX = doY = doZ = doW = TRUE;
				if (!fcurveMode) {
					if (!(key->flags&IKEY_XSEL)) doX = FALSE;
					if (!(key->flags&IKEY_YSEL)) doY = FALSE;
					if (!(key->flags&IKEY_ZSEL)) doZ = FALSE;
					if (!(key->flags&IKEY_WSEL)) doW = FALSE;
					}

				switch (anim->SuperClassID()) {
					case CTRL_FLOAT_CLASS_ID:			
						cont->GetValue(key->time,&f,FOREVER);
						f = CompRand(f-min,f+max);
						cont->SetValue(key->time,&f);
						break;

					case CTRL_POSITION_CLASS_ID:
					case CTRL_POINT3_CLASS_ID:
						cont->GetValue(key->time,&pt,FOREVER);
						if (doX) pt.x = CompRand(pt.x-min,pt.x+max);
						if (doY) pt.y = CompRand(pt.y-min,pt.y+max);
						if (doZ) pt.z = CompRand(pt.z-min,pt.z+max);
						cont->SetValue(key->time,&pt);
						break;
					
					case CTRL_POINT4_CLASS_ID:
						cont->GetValue(key->time,&p4,FOREVER);
						if (doX) p4.x = CompRand(p4.x-min,p4.x+max);
						if (doY) p4.y = CompRand(p4.y-min,p4.y+max);
						if (doZ) p4.z = CompRand(p4.z-min,p4.z+max);
						if (doW) p4.w = CompRand(p4.w-min,p4.w+max);
						cont->SetValue(key->time,&p4);
						break;

					case CTRL_ROTATION_CLASS_ID:
						cont->GetValue(key->time,&q,FOREVER);
						QuatToEuler(q, ang);
						ang.x = CompRand(ang.x-min,ang.x+max);
						ang.y = CompRand(ang.y-min,ang.y+max);
						ang.z = CompRand(ang.z-min,ang.z+max);
						EulerToQuat(ang,q);
						cont->SetValue(key->time,&q);
						break;

					case CTRL_SCALE_CLASS_ID:
						cont->GetValue(key->time,&s,FOREVER);
						if (doX) s.s.x = CompRand(s.s.x-min,s.s.x+max);
						if (doY) s.s.y = CompRand(s.s.y-min,s.s.y+max);
						if (doZ) s.s.z = CompRand(s.s.z-min,s.s.z+max);
						cont->SetValue(key->time,&s);
						break;
					}
				}
			}

		
		}

	ResumeAnimate();

	theHold.Accept(GetString(IDS_RB_RANDOMIZEKEYS));
	ip->RedrawViews(ip->GetTime());
	}