Пример #1
0
RefResult Composite::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, 
   PartID& partID, RefMessage message ) {
	switch (message) {
		case REFMSG_CHANGE:			
			if (paramDlg) 
				paramDlg->Invalidate();
			if (pblock->LastNotifyParamID() == comptex_tex && pblock->Count(comptex_tex) != subTex.Count())
				SetNumMaps(pblock->Count(comptex_tex));
			else if (pblock->LastNotifyParamID() == comptex_ons && pblock->Count(comptex_ons) != subTex.Count())
				SetNumMaps(pblock->Count(comptex_ons));
			DiscardTexHandles(); // DS 5/4/00
			ivalid.SetEmpty();
			if (paramDlg&&Active())
				paramDlg->ip->MtlChanged();
			break;
		
		case REFMSG_GET_PARAM_DIM:
			return REF_STOP; 
		
		case REFMSG_GET_PARAM_NAME: {
			GetParamName *gpn = (GetParamName*)partID;
			gpn->name= GetSubTexmapSlotName(gpn->index);			
			return REF_STOP; 
			}
		}
	return(REF_SUCCEED);
	}
BOOL OrientConstRotation::AppendTarget(INode *target, float weight){

	if (target == NULL){
		float var = 50.0f;
		int ct = pblock->Count(orientation_target_list);
		int ctf = pblock->Count(orientation_target_weight);
		theHold.Begin();
		pblock->SetCount(orientation_target_list, ct + 1);
		pblock->SetValue(orientation_target_list, GetCOREInterface()->GetTime(), target, ct);
		pblock->Append(orientation_target_weight, 1, &var, 1);
		theHold.Accept(GetString(IDS_AG_ORIENTATION_LIST));
		return TRUE;
	}
	else if (!(target->TestForLoop(FOREVER,(ReferenceMaker *) this)!=REF_SUCCEED)) 
	{
		for (int i = 0; i < pblock->Count(orientation_target_list); i++){
			if (target == pblock->GetINode(orientation_target_list, GetCOREInterface()->GetTime(), i)){
				return FALSE; // the target is already in the targetlist
			}
		}
			
		theHold.Begin();
		pblock->Append(orientation_target_list, 1, &target, 1);
		pblock->Append(orientation_target_weight, 1, &weight, 1);
		theHold.Accept(GetString(IDS_AG_ORIENTATION_LIST));
		return TRUE;
	}
	return FALSE;


}
void plResponderComponent::IFixOldPB()
{
    if (fCompPB)
    {
        if (fCompPB->Count(kResponderState) == 0)
        {
            IParamBlock2 *pb = CreateParameterBlock2(&gStateBlock, nil);
            int idx = fCompPB->Append(kResponderState, 1, (ReferenceTarget**)&pb);
            pb->SetValue(kStateCmdSwitch, 0, idx);
        }
        if (fCompPB->Count(kResponderStateName) == 0)
        {
            char *name = "";
            fCompPB->Append(kResponderStateName, 1, &name);
        }

        // Make sure there is an enabled value for each command in the state
        for (int i = 0; i < fCompPB->Count(kResponderState); i++)
        {
            IParamBlock2* pb = (IParamBlock2*)fCompPB->GetReferenceTarget(kResponderState, 0, i);
            if (pb->Count(kStateCmdEnabled) != pb->Count(kStateCmdParams))
                pb->SetCount(kStateCmdEnabled, pb->Count(kStateCmdParams));
        }
    }
}
BOOL OrientConstRotation::DeleteTarget(int selection){
	int ct = pblock->Count(orientation_target_list);
	if (selection >= 0 && selection < pblock->Count(orientation_target_list)){
//		theHold.Begin();
		pblock->Delete(orientation_target_weight, selection, 1);
		pblock->Delete(orientation_target_list, selection, 1);
//		theHold.Accept(GetString(IDS_AG_ORIENTATION_LIST));
		return TRUE;
	}
	else
		return FALSE;

}
const char* plResponderProc::GetCommandName(int cmdIdx)
{
    static char buf[256];

    if (fStatePB->Count(kStateCmdParams) > cmdIdx)
    {
        buf[0] = '\0';

        BOOL enabled = fStatePB->GetInt(kStateCmdEnabled, 0, cmdIdx);
        if (!enabled)
            strcat(buf, "[D]");

        IParamBlock2 *cmdPB = (IParamBlock2*)fStatePB->GetReferenceTarget(kStateCmdParams, 0, cmdIdx);
        plResponderCmd *cmd = plResponderCmd::Find(cmdPB);

        IParamBlock2 *waitPB = (IParamBlock2*)fStatePB->GetReferenceTarget(kStateCmdWait, 0, cmdIdx);
        int waitingOn = ResponderWait::GetWaitingOn(waitPB);
        if (waitingOn != -1)
        {
            char num[10];
            sprintf(num, "(%d)", waitingOn+1);
            strcat(buf, num);
        }

        strcat(buf, cmd->GetInstanceName(cmdPB));

        return buf;
    }

    hsAssert(0, "Bad index to GetCommandName");
    return nil;
}
void plResponderProc::AddCommand()
{
    RECT rect;
    GetWindowRect(GetDlgItem(fhDlg, IDC_ADD_CMD), &rect);

    // Create the popup menu and get the option the user selects
    SetForegroundWindow(fhDlg);
    int type = TrackPopupMenu(fhMenu, TPM_RIGHTALIGN | TPM_NONOTIFY | TPM_RETURNCMD, rect.left, rect.top, 0, fhDlg, NULL);
    PostMessage(fhDlg, WM_USER, 0, 0);

    if (type == 0)
        return;

    CmdID& cmdID = fMenuCmds[type];
    plResponderCmd *cmd = cmdID.first;
    int cmdIdx = cmdID.second;

    IParamBlock2 *cmdPB = cmd->CreatePB(cmdIdx);
    fStatePB->Append(kStateCmdParams, 1, (ReferenceTarget**)&cmdPB);

    IParamBlock2 *waitPB = ResponderWait::CreatePB();
    fStatePB->Append(kStateCmdWait, 1, (ReferenceTarget**)&waitPB);

    BOOL enabled = TRUE;
    fStatePB->Append(kStateCmdEnabled, 1, &enabled);

    const char* name = GetCommandName(fStatePB->Count(kStateCmdParams)-1);
    int idx = ListBox_AddString(fhList, name);
    ListBox_SetCurSel(fhList, idx);

    ICreateCmdRollups();
}
INode* OrientConstRotation::GetNode(int targetNumber){
	if (targetNumber >= 0 && targetNumber < pblock->Count(orientation_target_list)){
		INode *orient_targ;
		pblock->GetValue(orientation_target_list, 0, orient_targ, FOREVER, targetNumber);
		return orient_targ;
	}
	return NULL;
}
void OrientConstRotation::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
{
	if (firstTimeFlag) {
		Point3 trans, scaleP;
		Quat quat;
		Matrix3 tempMat(1);
		// CAL-9/26/2002: in absolute mode the value could be un-initialized (random value).
		if (method == CTRL_RELATIVE) tempMat = *(Matrix3*)val;
		DecomposeMatrix(tempMat, trans, quat, scaleP);
		baseRotQuatWorld = baseRotQuatLocal * quat;
		baseRotQuatWorld.Normalize();
		firstTimeFlag = 0;
	}
	if (!ivalid.InInterval(t)) {
		DbgAssert(val != NULL);
		Update(t);
	}
	valid &= ivalid;

			 
	if (method==CTRL_RELATIVE) {
		Interval iv;

		if (IsLocal()){			// From Update, I'm getting target_local_TM in curRot
			Matrix3 *mat = (Matrix3*)val; // this is source_Parent_TM
			Quat q = curRot;			// this is target_local_TM
			PreRotateMatrix(*mat, q);	// source_world_TM = source_Parent_TM * target_local_TM 
		}
		
		else { 		// i.e., WorldToWorld: from Update, I'm getting target_world_TM in curRot
			int ct = pblock->Count(orientation_target_list);;
			if (ct < 1){
				Matrix3 *mat = (Matrix3*)val;
				Quat q = curRot;
				PreRotateMatrix(*mat, q);
			}
			else{
				Matrix3 *mat = (Matrix3*)val; // this is source_Parent_TM
				// CAL-06/24/02: preserve all components and replace with the new orientation.
				AffineParts ap;
				decomp_affine( *mat, &ap );
				ap.q = curRot;				// target world rotation
				comp_affine( ap, *mat );
				// CAL-06/24/02: this only preserve the translation component
				// Point3 tr;
				// tr = mat->GetTrans();
				// mat->IdentityMatrix();
				// Quat q = curRot;			// this is target_world_TM
				// q.MakeMatrix(*mat);
				// mat->SetTrans(tr);
			}
		}
	} 
	else {
		*((Quat*)val) = curRot;
	}
//		RedrawListbox(GetCOREInterface()->GetTime());
}
BOOL OrientConstRotation::SetTargetWeight(int targetNumber, float weight){
	if (targetNumber >= 0 && targetNumber < pblock->Count(orientation_target_list)){
		pblock->SetValue(orientation_target_weight, GetCOREInterface()->GetTime(), weight, targetNumber);
		return TRUE;
	}
	else{
		return FALSE;
	}
}
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+
//|					custom UI update for Duration Test  					 |
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+
INT_PTR TestSpawnOnCollisionDlgProc::DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) 
	{
	IParamBlock2* pblock;
	case WM_INITDIALOG:
		pblock = map->GetParamBlock();
		UpdateSpawnTypeDlg( hWnd, pblock->GetInt(kSpawnCollision_spawnType,t),
								  pblock->GetInt(kSpawnCollision_deleteParent,t) );
		UpdateSpeedTypeDlg( hWnd, pblock->GetInt(kSpawnCollision_speedType,t) );
		UpdateRandomSeedDlg( hWnd, pblock->GetFloat(kSpawnCollision_spawnAble,t),
								   pblock->GetFloat(kSpawnCollision_numVariation,t),
								   pblock->GetFloat(kSpawnCollision_speedVariation,t),
								   pblock->GetFloat(kSpawnCollision_speedDivergence,t),
								   pblock->GetFloat(kSpawnCollision_scaleVariation,t) );						   
		break;
	case WM_COMMAND:
		pblock = map->GetParamBlock();
		switch (LOWORD(wParam))
		{
		case IDC_NEW:
			if (pblock) pblock->NotifyDependents(FOREVER, PART_OBJ, kSpawnCollision_RefMsg_NewRand);
			return TRUE;
		case IDC_COLLISION_PICKNODE:
			if (pblock) pblock->NotifyDependents( FOREVER, 0, kSpawnCollision_RefMsg_ResetValidatorAction );
			break;
		case IDC_BYLIST:
			if (pblock) pblock->NotifyDependents( FOREVER, 0, kSpawnCollision_RefMsg_ListSelect );
			break;
		case kSpawnCollision_message_type:
			pblock = map->GetParamBlock();
			UpdateSpawnTypeDlg( hWnd, pblock->GetInt(kSpawnCollision_spawnType,t),
									  pblock->GetInt(kSpawnCollision_deleteParent,t) );
			break;
		case kSpawnCollision_message_speed:
			pblock = map->GetParamBlock();
			UpdateSpeedTypeDlg( hWnd, pblock->GetInt(kSpawnCollision_speedType,t) );
			break;
		case kSpawnCollision_message_random:
			pblock = map->GetParamBlock();
			UpdateRandomSeedDlg( hWnd, pblock->GetFloat(kSpawnCollision_spawnAble,t),
									   pblock->GetFloat(kSpawnCollision_numVariation,t),
									   pblock->GetFloat(kSpawnCollision_speedVariation,t),
									   pblock->GetFloat(kSpawnCollision_speedDivergence,t),
									   pblock->GetFloat(kSpawnCollision_scaleVariation,t) );						   
			break;
		case kSpawnCollision_message_deflectors:
			pblock = map->GetParamBlock();
			if (pblock)
				UpdateDeflectorsDlg( hWnd, pblock->Count(kSpawnCollision_deflectors) );
			break;
		}
		break;
	}
	return FALSE;
}
float OrientConstRotation::GetTargetWeight(int targetNumber){
	if (targetNumber >= 0 && targetNumber < pblock->Count(orientation_target_list)){
		float targetWt;
		pblock->GetValue(orientation_target_weight, GetCOREInterface()->GetTime(), targetWt, FOREVER, targetNumber);
		return targetWt;
	}
	else{
		return 0.0f;
	}
}
void plResponderProc::LoadList()
{
    ListBox_ResetContent(fhList);

    for (int i = 0; i < fStatePB->Count(kStateCmdParams); i++)
    {
        const char* name = GetCommandName(i);
        ListBox_AddString(fhList, name);
    }

    ListBox_SetCurSel(fhList, -1);
}
void plResponderComponent::IConvertCmds(plMaxNode* node, plErrorMsg* pErrMsg, int state, CmdIdxs& cmdIdxs)
{
    IParamBlock2 *statePB = (IParamBlock2*)fCompPB->GetReferenceTarget(kResponderState, 0, state);
    plResponderModifier *responder = IGetResponderMod(node);

    // Add the messages to the logic modifier
    for (int i = 0; i < statePB->Count(kStateCmdParams); i++)
    {
        plMessage *msg = nil;

        BOOL enabled = statePB->GetInt(kStateCmdEnabled, 0, i);
        if (!enabled)
            continue;

        IParamBlock2 *cmdPB = (IParamBlock2*)statePB->GetReferenceTarget(kStateCmdParams, 0, i);

        try
        {
            plResponderCmd *cmd = plResponderCmd::Find(cmdPB);
            if (cmd)
                msg = cmd->CreateMsg(node, pErrMsg, cmdPB);
        }
        catch (char *reason)
        {
            char buf[512];

            char stateName[128];
            const char *curStateName = fCompPB->GetStr(kResponderStateName, 0, state);
            if (curStateName && *curStateName != '\0')
                strcpy(stateName, fCompPB->GetStr(kResponderStateName, 0, state));
            else
                sprintf(stateName, "State %d", state+1);

            sprintf(buf,
                "A responder command failed to export.\n\nResponder:\t%s\nState:\t\t%s\nCommand:\t%d\n\nReason: %s",
                GetINode()->GetName(), stateName, i+1, reason);

            pErrMsg->Set(true, "Responder Warning", buf).Show();
            pErrMsg->Set(false);
        }

        if (msg)
        {
            msg->SetSender(responder->GetKey());
            responder->AddCommand(msg, state);
            int idx = responder->fStates[state].fCmds.Count()-1;
            cmdIdxs[i] = idx;
        }
    }
}
Пример #14
0
void Composite::Update(TimeValue t, Interval& valid) 
	{
	if (!ivalid.InInterval(t)) {
		ivalid.SetInfinite();		
		int n = pblock->Count(comptex_ons);
		if (n!=mapOn.Count()) mapOn.SetCount(n);
		for (int i=0; i<subTex.Count(); i++) {
			pblock->GetValue(comptex_ons,0,mapOn[i],valid,i);
	
			if (subTex[i]) 
				subTex[i]->Update(t,ivalid);
			}
		}
	valid &= ivalid;
	}
hsBool plResponderComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg)
{
    int numStates = fCompPB->Count(kResponderState);
    for (int i = 0; i < numStates; i++)
    {
        IParamBlock2 *statePB = (IParamBlock2*)fCompPB->GetReferenceTarget(kResponderState, 0, i);

        for (int j = 0; j < statePB->Count(kStateCmdParams); j++)
        {
            IParamBlock2 *cmdPB = (IParamBlock2*)statePB->GetReferenceTarget(kStateCmdParams, 0, j);
            plResponderCmd *cmd = plResponderCmd::Find(cmdPB);
            cmd->SetupProperties(node, pErrMsg, cmdPB);
        }
    }

    return true;
}
void plResponderComponent::IConvertCmdWaits(plMaxNode* node, plErrorMsg* pErrMsg,
                                            int state, CmdIdxs& cmdIdxs, int &numCallbacks)
{
    IParamBlock2 *statePB = (IParamBlock2*)fCompPB->GetReferenceTarget(kResponderState, 0, state);
    plResponderModifier *responder = IGetResponderMod(node);
    hsTArray<plResponderModifier::plResponderCmd>& cmds = responder->fStates[state].fCmds;

    int numWaits = statePB->Count(kStateCmdWait);
    for (int i = 0; i < numWaits; i++)
    {
        IParamBlock2 *waitPB = GetWaitBlk(statePB, i);

        int wait = ResponderWait::GetWaitingOn(waitPB);

        // If the waiter and waitee both converted, create the callback
        if (cmdIdxs.find(wait) != cmdIdxs.end() && cmdIdxs.find(i) != cmdIdxs.end())
        {
            int convertedIdx = cmdIdxs[wait];

            ResponderWaitInfo waitInfo;
            waitInfo.responderName = plString::FromUtf8(GetINode()->GetName());
            waitInfo.receiver = responder->GetKey();
            waitInfo.callbackUser = numCallbacks++;
            waitInfo.msg = cmds[convertedIdx].fMsg;
            waitInfo.point = ResponderWait::GetWaitPoint(waitPB);

            responder->AddCallback(state, convertedIdx, waitInfo.callbackUser);
            cmds[cmdIdxs[i]].fWaitOn = waitInfo.callbackUser;

            IParamBlock2 *pb = (IParamBlock2*)statePB->GetReferenceTarget(kStateCmdParams, 0, wait);
            plResponderCmd *cmd = plResponderCmd::Find(pb);

            cmd->CreateWait(node, pErrMsg, pb, waitInfo);
        }
    }
}
Пример #17
0
BOOL plClothingComponentProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    IParamBlock2 *pb = pm->GetParamBlock();
    HWND hList = GetDlgItem(hWnd, IDC_CLOTHING_LIST);
    HWND hGroup = GetDlgItem(hWnd, IDC_CLOTHING_GROUP);
    HWND hType = GetDlgItem(hWnd, IDC_CLOTHING_TYPE);
    HWND hLOD = GetDlgItem(hWnd, IDC_COMP_LOD_CLOTHING_STATE);
    switch (msg)
    {
    case WM_INITDIALOG:
        {
            ListBox_ResetContent(hList);
            int i;
            for (i = 0; i < pb->Count(plClothingComponent::kMaterials); i++)
                ListBox_AddString(hList, pb->GetMtl(ParamID(plClothingComponent::kMaterials), 0, i)->GetName());

            ListBox_SetCurSel(hList, -1);

            for (i = 0; i < plClothingMgr::kMaxGroup; i++)
                ComboBox_AddString(hGroup, plClothingMgr::GroupStrings[i]);
            ComboBox_SetCurSel(hGroup, pb->GetInt(plClothingComponent::kGroup));

            for (i = 0; i < plClothingMgr::kMaxType; i++)
                ComboBox_AddString(hType, plClothingMgr::TypeStrings[i]);
            ComboBox_SetCurSel(hType, pb->GetInt(plClothingComponent::kType));

            ComboBox_AddString(hLOD, "High");
            ComboBox_AddString(hLOD, "Medium");
            ComboBox_AddString(hLOD, "Low");
            ComboBox_SetCurSel(hLOD, pb->GetInt(plClothingComponent::kLODState));
        }
        return TRUE;


    case WM_COMMAND:
        if (HIWORD(wParam) == BN_CLICKED)
        {
            if (LOWORD(wParam) == IDC_CLOTHING_ADD)
            {
                Mtl *pickedMtl = plPickMaterialMap::PickMaterial(plMtlCollector::kClothingMtlOnly);
                if (pickedMtl != nil)
                {
                    LRESULT stringIdx = ListBox_FindStringExact(hList, -1, pickedMtl->GetName());
                    if (stringIdx == LB_ERR) // It's not already there, go and add it
                    {
                        pb->Append(ParamID(plClothingComponent::kMaterials), 1, &pickedMtl, 0);
                        ListBox_AddString(hList, pickedMtl->GetName());
                    }
                }
                return TRUE;
            }
            // Remove the currently selected material
            else if (LOWORD(wParam) == IDC_CLOTHING_REMOVE)
            {
                int sel = ListBox_GetCurSel(hList);
                if (sel != LB_ERR)
                {
                    pb->Delete(plClothingComponent::kMaterials, sel, 1);
                    ListBox_DeleteString(hList, sel);
                }
                return TRUE;
            }
            else if( LOWORD( wParam ) == IDC_CLOTHING_CLEARMESH )
            {
                int state = pb->GetInt(plClothingComponent::kLODState);
                pb->SetValue(plClothingComponent::kMeshNodeTab, 0, (INode*)nil, state );
                pb->Reset(plClothingComponent::kMeshNodeAddBtn);
            }
        }
        else if (LOWORD(wParam) == IDC_CLOTHING_GROUP)
        {
            int setIdx = ComboBox_GetCurSel(hGroup);
            pb->SetValue(plClothingComponent::kGroup, 0, setIdx);

            return TRUE;
        }
        else if (LOWORD(wParam) == IDC_CLOTHING_TYPE)
        {
            int setIdx = ComboBox_GetCurSel(hType);
            pb->SetValue(plClothingComponent::kType, 0, setIdx);

            return TRUE;
        }
        else
        {
            int state = pb->GetInt(plClothingComponent::kLODState);
                
            INode *node = pb->GetINode(plClothingComponent::kMeshNodeAddBtn);
            if (node)
                pb->SetValue(plClothingComponent::kMeshNodeTab, 0, node, state);

            if(LOWORD(wParam) == IDC_COMP_LOD_CLOTHING_STATE && HIWORD(wParam) == CBN_SELCHANGE)
            {
                int idx = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
                pb->SetValue(plClothingComponent::kLODState, 0, idx);
            
                node = pb->GetINode(plClothingComponent::kMeshNodeTab, 0, idx);
                if (node)
                    pb->SetValue(plClothingComponent::kMeshNodeAddBtn, 0, node);
                else
                    pb->Reset(plClothingComponent::kMeshNodeAddBtn);

                return TRUE;
            }
        }
    }

    return FALSE;
}
Пример #18
0
		int NumSubMtls() {return pblock2->Count(compmat_mtls);}  //how to handle this ??????
BOOL plResponderProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static UINT dragListMsg = 0;

    if (dragListMsg != 0 && msg == dragListMsg)
        if (DragListProc(hWnd, (DRAGLISTINFO*)lParam))
            return TRUE;

    switch (msg)
    {
    case WM_INITDIALOG:
        {
            if (!fhMenu)
                ICreateMenu();

            fhDlg = hWnd;
            fhList = GetDlgItem(fhDlg, IDC_CMD_LIST);
            fCurState = 0;
            fCmdIdx = -1;
            
            fPB = pm->GetParamBlock();
            fComp = (plResponderComponent*)fPB->GetOwner();

            fComp->IFixOldPB();

            LoadState();
            
            // Make it so the user can drag commands to different positions
            dragListMsg = RegisterWindowMessage(DRAGLISTMSGSTRING);
            MakeDragList(GetDlgItem(hWnd, IDC_CMD_LIST));

            // Setup the State Name combo
            HWND hStateName = GetDlgItem(hWnd, IDC_STATE_COMBO);
            ComboBox_LimitText(hStateName, 256);

// I give up, Windows doesn't want to tell me the real font size
#if 0//def CUSTOM_DRAW
            // TEMP
            HDC hDC = GetDC(hStateName);
            HFONT sysFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
            HFONT oldFont = SelectFont(hDC, sysFont);

            TEXTMETRIC tm;
            GetTextMetrics(hDC, &tm);
            ComboBox_SetItemHeight(hStateName, 0, tm.tmHeight+2);

            DeleteFont(SelectFont(hDC, oldFont));
            ReleaseDC(hStateName, hDC);
#endif

            // Add the commands
            int idx = ComboBox_AddString(hStateName, "Add State");
            ComboBox_SetItemData(hStateName, idx, kStateAdd);
            idx = ComboBox_AddString(hStateName, "Remove Current State");
            ComboBox_SetItemData(hStateName, idx, kStateRemove);
            idx = ComboBox_AddString(hStateName, "Set Current as Default");
            ComboBox_SetItemData(hStateName, idx, kStateDefault);
            idx = ComboBox_AddString(hStateName, "Copy Current State");
            ComboBox_SetItemData(hStateName, idx, kStateCopy);

            HWND hSwitchCombo = GetDlgItem(hWnd, IDC_SWITCH_COMBO);

            int numStates = fPB->Count(kResponderStateName);
            for (int i = 0; i < numStates; i++)
            {
                const char *stateName = fPB->GetStr(kResponderStateName, 0, i);
                char buf[128];
                if (!stateName || *stateName == '\0')
                {
                    sprintf(buf, "State %d", i+1);
                    stateName = buf;
                }
                ComboBox_InsertString(hStateName, i, stateName);
                ComboBox_AddString(hSwitchCombo, stateName);
            }

            ComboBox_SetCurSel(hStateName, fCurState);

            ComboBox_SetCurSel(hSwitchCombo, fStatePB->GetInt(kStateCmdSwitch));
        }
        return TRUE;

#ifdef CUSTOM_DRAW
    case WM_DRAWITEM:
        if (wParam == IDC_STATE_COMBO)
        {
            IDrawComboItem((DRAWITEMSTRUCT*)lParam);
            return TRUE;
        }
        break;
#endif

    case WM_SETCURSOR:
        {
            if (HIWORD(lParam) == WM_RBUTTONDOWN && HWND(wParam) == GetDlgItem(hWnd, IDC_CMD_LIST))
            {
                ICmdRightClick(HWND(wParam));
                return TRUE;
            }
        }
        break;
    
    case WM_COMMAND:
        if (HIWORD(wParam) == BN_CLICKED)
        {
            if (LOWORD(wParam) == IDC_ADD_ACTIVATOR)
            {
                // Adding an activator.  Set it and refresh the UI to show it in our list.
                plPick::Activator(fPB, kResponderActivators, false);
                pm->Invalidate(kResponderActivators);
                return TRUE;
            }
            else if (LOWORD(wParam) == IDC_ADD_CMD)
            {
                AddCommand();
                return TRUE;
            }
            // Remove the currently selected condition
            else if (LOWORD(wParam) == IDC_REMOVE_CMD)
            {
                RemoveCurCommand();
                return TRUE;
            }
        }
        else if (HIWORD(wParam) == LBN_SELCHANGE && LOWORD(wParam) == IDC_CMD_LIST)
        {
            ICreateCmdRollups();
            return TRUE;
        }
        else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_SWITCH_COMBO)
        {
            int sel = ComboBox_GetCurSel((HWND)lParam);
            if (sel != CB_ERR)
                fStatePB->SetValue(kStateCmdSwitch, 0, sel);
        }
        else if (LOWORD(wParam) == IDC_STATE_COMBO)
        {
            HWND hCombo = (HWND)lParam;
            int code = HIWORD(wParam);

            // Disable accelerators when the combo has focus, so that new names can be typed in
            if (code == CBN_SETFOCUS)
            {
                plMaxAccelerators::Disable();
                return TRUE;
            }
            else if (code == CBN_KILLFOCUS)
            {
                plMaxAccelerators::Enable();
                return TRUE;
            }
            // State name changed, save it in the PB
            else if (code == CBN_EDITCHANGE)
            {
                char buf[256];
                ComboBox_GetText(hCombo, buf, sizeof(buf));
                const char *curName = fPB->GetStr(kResponderStateName, 0, fCurState);
                if (!curName || strcmp(buf, curName))
                {
                    HWND hSwitch = GetDlgItem(hWnd, IDC_SWITCH_COMBO);
                    int sel = ComboBox_GetCurSel(hSwitch);
                    ComboBox_DeleteString(hSwitch, fCurState);
                    ComboBox_InsertString(hSwitch, fCurState, buf);
                    ComboBox_SetCurSel(hSwitch, sel);
                    
                    fPB->SetValue(kResponderStateName, 0, buf, fCurState);
                    ComboBox_DeleteString(hCombo, fCurState);
                    ComboBox_InsertString(hCombo, fCurState, buf);
//                  ComboBox_SetCurSel(hCombo, fCurState);
                }

                return TRUE;
            }
            else if (code == CBN_SELCHANGE)
            {
                int sel = ComboBox_GetCurSel(hCombo);
                int type = ComboBox_GetItemData(hCombo, sel);

                if (type == kStateAdd)
                {
                    IParamBlock2 *pb = CreateParameterBlock2(&gStateBlock, nil);
                    fCurState = AddState(pb);
                    fCmdIdx = -1;
                }
                else if (type == kStateRemove)
                {
                    int count = fPB->Count(kResponderState);
                    // Don't let the user remove the last state
                    if (count == 1)
                    {
                        hsMessageBox("You must have at least one state.", "Error", hsMessageBoxNormal);
                        ComboBox_SetCurSel(hCombo, fCurState);
                        return TRUE;
                    }
                    // Verify that the user really wants to delete the state
                    else
                    {
                        int ret = hsMessageBox("Are you sure you want to remove this state?", "Verify Remove", hsMessageBoxYesNo);
                        if (ret == hsMBoxNo)
                        {
                            ComboBox_SetCurSel(hCombo, fCurState);
                            return TRUE;
                        }
                    }

                    fPB->Delete(kResponderState, fCurState, 1);
                    fPB->Delete(kResponderStateName, fCurState, 1);

                    ComboBox_DeleteString(hCombo, fCurState);
                    ComboBox_SetCurSel(hCombo, 0);

                    HWND hSwitch = GetDlgItem(hWnd, IDC_SWITCH_COMBO);
                    ComboBox_DeleteString(hSwitch, fCurState);

                    // If the deleted state was the default, set the default to the first
                    int defState = fPB->GetInt(kResponderStateDef);
                    if (fCurState == defState)
                        fPB->SetValue(kResponderStateDef, 0, 0);
                    else if (fCurState < defState)
                        fPB->SetValue(kResponderStateDef, 0, defState-1);

                    // Patch up the switch commands
                    for (int i = fCurState; i < fPB->Count(kResponderState); i++)
                    {
                        IParamBlock2 *pb = (IParamBlock2*)fPB->GetReferenceTarget(kResponderState, 0, i);

                        int switchState = pb->GetInt(kStateCmdSwitch);
                        // TODO: might want to warn about this
                        if (switchState == fCurState)
                            pb->SetValue(kStateCmdSwitch, 0, 0);
                        else if (switchState > fCurState)
                            pb->SetValue(kStateCmdSwitch, 0, switchState-1);
                    }

                    fCurState = 0;
                    fCmdIdx = -1;
                }
                else if (type == kStateDefault)
                {
                    // Set the current state as the default
                    fPB->SetValue(kResponderStateDef, 0, fCurState);
                    ComboBox_SetCurSel(hCombo, fCurState);
                }
                else if (type == kStateCopy)
                {
                    // Clone the state PB
                    IParamBlock2 *origPB = (IParamBlock2*)fPB->GetReferenceTarget(kResponderState, 0, fCurState);
                    IParamBlock2 *copyPB = (IParamBlock2*)origPB->Clone(gMyRemapDir);
                    fCurState = AddState(copyPB);
                    fCmdIdx = -1;
                }
                else
                {
                    fCurState = sel;
                    fCmdIdx = -1;
                }

                LoadState();

                return TRUE;
            }
        }
    }

    return FALSE;
}
int OrientConstRotation::GetNumTargets(){
	return pblock->Count(orientation_target_list);
}
	void OrientConstRotation::RedrawListbox(TimeValue t,  int sel)
	{
		if (hWnd == NULL) return;
		if (!ip || editCont != this) return;
		int isWorldinListboxFlag = 0;
		if(!orientCD.NumParamMaps()) return;
		int selection = SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_GETCURSEL, 0, 0);
//		IParamBlock2* pb = orientCD.GetParamMap(0)->GetParamBlock();
		SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_RESETCONTENT, 0, 0);
		int ts = 64;  // appears smaller than necessary since for a large no of targets the vertical scroll bar needs space
		SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_SETTABSTOPS, 1, (LPARAM)&ts);
		int ct = pblock->Count(orientation_target_list);
		int ctf = pblock->Count(orientation_target_weight);
		if (ct != ctf) return;		// CAL-09/10/02: In the middle of changing table size.

		for (int i = 0; i < ct; i++){				
			TSTR str;
			INode *testNode;
			testNode = pblock->GetINode(orientation_target_list, t, i);
			if (testNode == NULL){
				str.printf( _T("%-s\t%-d"), // NOTE: for tab "\t" to use, check "use tabstops" in the resource listbox properties
										_T("World"), (int)pblock->GetFloat(orientation_target_weight, t, i));
				isWorldinListboxFlag = 1;
				ICustButton *iPickOb;
				iPickOb	= GetICustButton(GetDlgItem(hWnd, IDC_ORIENT_PICK_WORLD));
				if (iPickOb != NULL){
					iPickOb->Enable(FALSE);
					ReleaseICustButton(iPickOb);
				}
			}
			else{
				float wwt = pblock->GetFloat(orientation_target_weight, t, i);
				const TCHAR * nname = testNode->GetName();
				str.printf(_T("%-s\t%-d"), 
				testNode->GetName(),
				(int)pblock->GetFloat(orientation_target_weight, t, i));
			}
			SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) str.data());			
		}

		if(!isWorldinListboxFlag){
				ICustButton *iPickOb;
				iPickOb	= GetICustButton(GetDlgItem(hWnd, IDC_ORIENT_PICK_WORLD));
				if (iPickOb != NULL){
					iPickOb->Enable(TRUE);
					ReleaseICustButton(iPickOb);
				}
		}

		if (ct > 0){
			if (sel >= 0){
				SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_SETCURSEL, sel, 0);
			}
			else{
//		int selection = SendDlgItemMessage(hWnd, IDC_POS_TARG_LIST, LB_GETCURSEL, 0, 0);
				if (selection >= 0){
					SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_SETCURSEL, selection, 0);
					last_selection = selection;
				}
				else if (ct == 1){
					SendDlgItemMessage(hWnd, IDC_ORIENT_TARG_LIST, LB_SETCURSEL, 0, 0);
					last_selection = 0;
				}
			}
			
			ISpinnerControl* spin = GetISpinner(GetDlgItem(hWnd, IDC_ORIENT_CONS_WEIGHT_SPINNER));
			if (last_selection >= 0 && spin != NULL){
				float value = pblock->GetFloat(orientation_target_weight, GetCOREInterface()->GetTime(), last_selection);
				spin->SetValue(value, FALSE);
			}
			ReleaseISpinner(spin);
		}
		HWND hListBox = GetDlgItem(hWnd, IDC_ORIENT_TARG_LIST);
		int extent = computeHorizontalExtent(hListBox, TRUE, 1, &ts);
		SendMessage(hListBox, LB_SETHORIZONTALEXTENT, extent, 0);
		UpdateWindow(hWnd);
	}
void OrientConstRotation::Update(TimeValue t){
	Interval iv = FOREVER;
	ivalid = FOREVER;
	
	int ct = pblock->Count(orientation_target_list);
	int ctf = pblock->Count(orientation_target_weight);

	float total_orient_target_weight_prev = 0.0f, total_orient_target_weight_current = 0.0f;
	float orient_targ_Wt_current = 0.0f;
	Quat quat_prev, quat_current, lCurRot;
	INode *orient_target_prev= NULL, *orient_target_current= NULL;
	Matrix3 targetTM(1);
	Point3 trans, scaleP;

	quat_prev.Identity();
	quat_current.Identity();
	lCurRot.Identity();

		if (ct == 1){
			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}
		}
		else if (ct > 1){

			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
//			if (orient_target_prev != NULL)
//			{
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}

			for (int i = 0; i < ct -1; i++) {
//				ct = pblock->Count(orientation_target_list);
				pblock->GetValue(orientation_target_list, t, orient_target_current, iv, i+1);
				pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, i+1);
//				if (orient_target_current != NULL){
					ivalid &= iv;

					if (orient_target_current == NULL){
						targetTM.IdentityMatrix();
					}
					else {
						targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					}

//					Matrix3 targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					if (IsLocal() && orient_target_current != NULL) {
						targetTM = targetTM * Inverse(orient_target_current->GetParentTM(t));
					}
					AffineParts comps;		// Requires header decomp.h
					decomp_affine(targetTM, &comps);
					quat_current = comps.q;
					quat_current.Normalize();
					quat_current.MakeClosest(quat_prev);

					float slerp_wt = 0.0f;
					if ((total_orient_target_weight_prev + orient_targ_Wt_current) != 0.0){
						slerp_wt = orient_targ_Wt_current / (total_orient_target_weight_prev + orient_targ_Wt_current);
					}

					lCurRot = Slerp(quat_prev, quat_current, slerp_wt);
					lCurRot.Normalize();

					quat_prev = lCurRot;
					total_orient_target_weight_prev += orient_targ_Wt_current;
//				}
			}			//for (int i = 0; i < ct -1; i++)
		}				//else if (ct > 1)

		if (oldTargetNumber != ct) {
			InitialOrientQuat = lCurRot;
		}

		curRot = lCurRot;
		if (total_orient_target_weight_prev > 0.0){
			if (Relative()){
				if(IsLocal()){
					curRot =   baseRotQuatLocal * (lCurRot /InitialOrientQuat);
				}
				else{
					curRot =   baseRotQuatWorld * (lCurRot /InitialOrientQuat);
				}
			}
		}
		else {
			curRot = baseRotQuatLocal;
		}
		curRot.MakeClosest(IdentQuat());
		curRot.Normalize();
		oldTargetNumber = ct;
//	if (ivalid.Empty()) ivalid.SetInstant(t);
}
void PAOperatorObjectDlgProc::UpdateDlg(IParamMap2* map, HWND hWnd)
{
//	BOOL bAxes, bDivergence, bRandom;
//	bool varAnimated, divAnimated;
	if(map && hWnd) {
		IParamBlock2* ppb = map->GetParamBlock();
		if(ppb) {
			bool enableGeometry = true;
			bool enableSubMtl = false;
			bool enableMapping = false;
			bool enableLockClosest = false;
		
			int type = ppb->GetInt(kObject_channelType, 0);
			bool isFloatType = (type == kObject_channelType_float);
			EnableWindow( GetDlgItem(hWnd, IDC_FLOATTYPE), isFloatType );
			int showControl = isFloatType ? SW_SHOW : SW_HIDE;
			ShowWindow( GetDlgItem( hWnd, IDC_FLOATTYPE), showControl);
			if (isFloatType) {
				switch(ppb->GetInt(kObject_propertyFloat, 0)) {
				case kObject_propertyFloat_distanceToPivot:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_DISTANCETOPIVOT));
					break;
				case kObject_propertyFloat_distanceToVertex:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_DISTANCETOVERTEX));
					break;
				case kObject_propertyFloat_distanceToSurface:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_DISTANCETOSURFACE));
					break;
				case kObject_propertyFloat_objectSpinRate:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTSPINRATE));
					break;
				case kObject_propertyFloat_pointLuminance:
					enableSubMtl = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_POINTLUMINANCE));
					break;
				case kObject_propertyFloat_pointOpacity:
					enableSubMtl = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_POINTOPACITY));
					break;
				case kObject_propertyFloat_faceSquare:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_FACESQUARE));
					break;
				case kObject_propertyFloat_softSelection:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_SOFTSELECTION));
					break;
				}
			}

			bool isIntType = (type == kObject_channelType_integer);
			EnableWindow( GetDlgItem(hWnd, IDC_INTTYPE), isIntType );
			showControl = isIntType ? SW_SHOW : SW_HIDE;
			ShowWindow( GetDlgItem( hWnd, IDC_INTTYPE), showControl);
			if (isIntType) {
				switch (ppb->GetInt(kObject_propertyInteger, 0)) {
				case kObject_propertyInteger_objectIndexByPivot:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTINDEXBYPIVOT));
					break;
				case kObject_propertyInteger_objectIndexByVertex:
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTINDEXBYVERTEX));
					break;
				case kObject_propertyInteger_objectIndexBySurface:
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTINDEXBYSURFACE));
					break;
				case kObject_propertyInteger_vertexIndex:
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_VERTEXINDEX));
					break;
				case kObject_propertyInteger_faceIndex:
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_FACEINDEX));
					break;
				case kObject_propertyInteger_materialIndex:
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_MATERIALINDEX));
					break;
				}
			}

			bool isVectorType = (type == kObject_channelType_vector);
			EnableWindow( GetDlgItem(hWnd, IDC_VECTORTYPE2), isVectorType );
			showControl = isVectorType ? SW_SHOW : SW_HIDE;
			ShowWindow( GetDlgItem( hWnd, IDC_VECTORTYPE2), showControl);
			if (isVectorType) {
				int vectorType = ppb->GetInt(kObject_propertyVector, 0);
				switch(vectorType) {
				case kObject_propertyVector_objectPosition:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTPOSITION));
					break;
				case kObject_propertyVector_objectSpeed:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTSPEED));
					break;
				case kObject_propertyVector_objectScale:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTSCALE));
					break;
				case kObject_propertyVector_objectEuclideRotation:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTEUCLIDEROTATION));
					break;
				case kObject_propertyVector_objectSpinAxis:
					enableGeometry = false;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_OBJECTSPINAXIS));
					break;
				case kObject_propertyVector_nearestColor:
					enableSubMtl = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_NEARESTCOLOR));
					break;
				case kObject_propertyVector_nearestMapping:
					enableMapping = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_NEARESTMAPPING));
					break;
				case kObject_propertyVector_mappingUVector:
					enableMapping = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_MAPPINGUVECTOR));
					break;
				case kObject_propertyVector_mappingVVector:
					enableMapping = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_MAPPINGVVECTOR));
					break;
				case kObject_propertyVector_mappingWVector:
					enableMapping = true;
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_MAPPINGWVECTOR));
					break;
				case kObject_propertyVector_nearestSurfacePoint:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_NEARESTSURFACEPOINT));
					break;
				case kObject_propertyVector_nearestVertex:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_NEARESTVERTEX));
					break;
				case kObject_propertyVector_nearestNormal:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_NEARESTNORMAL));
					break;
				case kObject_propertyVector_localSpeed:
					enableLockClosest = true;
					SetDlgItemText( hWnd, IDC_TEXT_PROPERTY, GetString(IDS_DESCRIPTION_LOCALSPEED));
					break;
				}
			}
		
			ISpinnerControl* spin = NULL;
			bool useSubMtl = (ppb->GetInt(kObject_useSubMtl, 0) != 0);
			EnableWindow( GetDlgItem(hWnd, IDC_USESUBMATERIAL), enableSubMtl );
			spin = GetISpinner( GetDlgItem( hWnd, IDC_SUBMATERIALSPIN) );
			spin->Enable(enableSubMtl && useSubMtl);
			ReleaseISpinner(spin);
			
			EnableWindow( GetDlgItem(hWnd, IDC_TEXT_MAPPINGCHANNEL), enableMapping );
			spin = GetISpinner( GetDlgItem( hWnd, IDC_MAPPINGCHANNELSPIN) );
			spin->Enable(enableMapping);
			ReleaseISpinner(spin);

//			if (enableLockClosest) // lockClosest is not used at the moment
//				if (ppb->GetInt(kObject_assignOnce, 0) != 0) enableLockClosest = false;
//			EnableWindow( GetDlgItem(hWnd, IDC_LOCK), enableLockClosest );

			int numObjects = ppb->Count(kObject_objects);
			EnableWindow( GetDlgItem(hWnd, IDC_REMOVENODE), numObjects > 0 );

			bool useDesignate = (ppb->GetInt(kObject_useDesignate, 0) != 0);
			EnableWindow( GetDlgItem(hWnd, IDC_TEXT_CUSTOMNAME2), useDesignate);
			EnableWindow( GetDlgItem(hWnd, IDC_CHANNELNAME2), useDesignate);
			
			bool useSyncChannel = (ppb->GetInt(kObject_sync, 0) == kObject_sync_channel);
			EnableWindow( GetDlgItem(hWnd, IDC_TEXT_CUSTOMNAME3), useSyncChannel);
			EnableWindow( GetDlgItem(hWnd, IDC_CHANNELNAME3), useSyncChannel);

			EnableWindow( GetDlgItem(hWnd, IDC_ANIMATED), enableGeometry);
			bool animatedShape = (ppb->GetInt(kObject_animated, 0) != 0);
			EnableWindow( GetDlgItem(hWnd, IDC_GEOMETRY), enableGeometry && animatedShape);

			bool useFilter = (ppb->GetInt(kObject_useCondition, 0) != 0);
			EnableWindow( GetDlgItem(hWnd, IDC_TEXT_CONDITIONNAME2), useFilter);
			EnableWindow( GetDlgItem(hWnd, IDC_CONDITIONNAME2), useFilter);
		}
	}
}
void SaveMetaData(INode* node, AlembicObject* object)
{
  if (object == NULL) {
    return;
  }
  if (object->GetNumSamples() > 0) {
    return;
  }

  Modifier* pMod = FindModifier(node, Class_ID(0xd81fc3e, 0x1e4eacf5));

  bool bReadCustAttribs = false;
  if (!pMod) {
    pMod = FindModifier(node, "Metadata");
    bReadCustAttribs = true;
  }

  if (!pMod) {
    return;
  }

  std::vector<std::string> metaData;

  if (bReadCustAttribs) {
    ICustAttribContainer* cont = pMod->GetCustAttribContainer();
    if (!cont) {
      return;
    }
    for (int i = 0; i < cont->GetNumCustAttribs(); i++) {
      CustAttrib* ca = cont->GetCustAttrib(i);
      std::string name = EC_MCHAR_to_UTF8(ca->GetName());

      IParamBlock2* pblock = ca->GetParamBlockByID(0);
      if (pblock) {
        int nNumParams = pblock->NumParams();
        for (int i = 0; i < nNumParams; i++) {
          ParamID id = pblock->IndextoID(i);
          // MSTR name = pblock->GetLocalName(id, 0);
          MSTR value = pblock->GetStr(id, 0);
          metaData.push_back(EC_MSTR_to_UTF8(value));
        }
      }
    }
  }
  else {
    IParamBlock2* pblock = pMod->GetParamBlockByID(0);
    if (pblock && pblock->NumParams() == 1) {
      ParamID id = pblock->IndextoID(0);
      MSTR name = pblock->GetLocalName(id, 0);
      int nSize = pblock->Count(id);

      for (int i = 0; i < nSize; i++) {
        MSTR value = pblock->GetStr(id, 0, i);
        metaData.push_back(EC_MSTR_to_UTF8(value));
      }
    }
  }

  if (metaData.size() > 0) {
    Abc::OStringArrayProperty metaDataProperty = Abc::OStringArrayProperty(
        object->GetCompound(), ".metadata", object->GetCompound().getMetaData(),
        object->GetCurrentJob()->GetAnimatedTs());
    Abc::StringArraySample metaDataSample(&metaData.front(), metaData.size());
    metaDataProperty.set(metaDataSample);
  }
}