//needs to remain int (instead of int32) since numbers are derived from TPL that uses int void FLiveEditorManager::Dispatch( int Status, int Data1, int Data2, const struct FLiveEditorDeviceData &Data ) { int Type = (Status & 0xF0) >> 4; int Channel = (Status % 16) + 1; int ControlID = Data1; int ID = LISTENER_ID(Channel,ControlID); int Delta = 0; //needs to remain int (instead of int32) since numbers are derived from TPL that uses int // // Dispatch the MIDI data to all Active Listners // TArray<ILiveEditListener*> Results; EventListeners.MultiFind( ID, Results ); for ( TArray<ILiveEditListener*>::TIterator It(Results); It; It++ ) { ILiveEditListener *Listener = *It; if ( !Listener || !Listener->Target.IsValid() ) { continue; } switch ( Listener->Binding.ControlType ) { case ELiveEditControllerType::NoteOnOff: Delta = 0; break; case ELiveEditControllerType::ControlChangeContinuous: if ( Data2 == Data.ContinuousIncrement ) Delta = 1; else if ( Data2 == Data.ContinuousDecrement ) Delta = -1; else Delta = 0; break; case ELiveEditControllerType::ControlChangeFixed: Delta = Data2 - Listener->Binding.LastValue; Listener->Binding.LastValue = Data2; default: break; } UObject *Target = Listener->Target.Get(); FLiveEditorManager_Dispatch_Parms Parms; Parms.Delta = Delta; Parms.MidiValue = (int32)Data2; Parms.ControlType = Listener->Binding.ControlType; Target->ProcessEvent( Target->FindFunctionChecked( Listener->Name ), &Parms ); } }
void FObjectReplicator::PostReceivedBunch() { // Call PostNetReceive const bool bIsServer = (OwningChannel->Connection->Driver->ServerConnection == NULL); if (!bIsServer && bHasReplicatedProperties) { PostNetReceive(); bHasReplicatedProperties = false; } // Check if PostNetReceive() destroyed Object UObject *Object = GetObject(); if (Object == NULL || Object->IsPendingKill()) { return; } RepLayout->CallRepNotifies( RepState, Object ); // Call RepNotifies if ( RepNotifies.Num() > 0 ) { for (int32 RepNotifyIdx = 0; RepNotifyIdx < RepNotifies.Num(); RepNotifyIdx++) { //UE_LOG(LogNet, Log, TEXT("Calling Object->%s with %s"), *RepNotifies(RepNotifyIdx)->RepNotifyFunc.ToString(), *RepNotifies(RepNotifyIdx)->GetName()); UProperty* RepProperty = RepNotifies[RepNotifyIdx]; UFunction* RepNotifyFunc = Object->FindFunctionChecked(RepProperty->RepNotifyFunc); if (RepNotifyFunc->NumParms == 0) { Object->ProcessEvent(RepNotifyFunc, NULL); } else if (RepNotifyFunc->NumParms == 1) { Object->ProcessEvent(RepNotifyFunc, RepProperty->ContainerPtrToValuePtr<uint8>(RepState->StaticBuffer.GetTypedData()) ); } else if (RepNotifyFunc->NumParms == 2) { // Fixme: this isn't as safe as it could be. Right now we have two types of parameters: MetaData (a TArray<uint8>) // and the last local value (pointer into the Recent[] array). // // Arrays always expect MetaData. Everything else, including structs, expect last value. // This is enforced with UHT only. If a ::NetSerialize function ever starts producing a MetaData array thats not in UArrayProperty, // we have no static way of catching this and the replication system could pass the wrong thing into ProcessEvent here. // // But this is all sort of an edge case feature anyways, so its not worth tearing things up too much over. FMemMark Mark(FMemStack::Get()); uint8* Parms = new(FMemStack::Get(),MEM_Zeroed,RepNotifyFunc->ParmsSize)uint8; TFieldIterator<UProperty> Itr(RepNotifyFunc); check(Itr); Itr->CopyCompleteValue( Itr->ContainerPtrToValuePtr<void>(Parms), RepProperty->ContainerPtrToValuePtr<uint8>(RepState->StaticBuffer.GetTypedData()) ); ++Itr; check(Itr); TArray<uint8> *NotifyMetaData = RepNotifyMetaData.Find(RepNotifies[RepNotifyIdx]); check(NotifyMetaData); Itr->CopyCompleteValue( Itr->ContainerPtrToValuePtr<void>(Parms), NotifyMetaData ); Object->ProcessEvent(RepNotifyFunc, Parms ); Mark.Pop(); } if (Object == NULL || Object->IsPendingKill()) { // script event destroyed Object break; } } } RepNotifies.Reset(); RepNotifyMetaData.Empty(); }