- Directive d'inclusion : #include DescValueMonitor.h
Un démon de cette classe est une structure permettant de spécifier des actions qui doivent être déclenchées lorsqu'on accède à la valeur d'un descripteur variable (par GetIntValue, GetFloatValue, GetDoubleValue, GetEntityValue, GetEntityTabValue, GetStringValue), ou bien lorsqu'on modifie cette valeur (par SetValue, AddValue, ).
Un tel démon est déclaré et défini comme une instance de la classe DescValueMonitor. DIESE ne permet que de spécifier des actions à déclencher lors de l'accès ou de la modification des descripteurs variables des entités. Aucune réaction ne pourra être associée aux descripteurs constants des entités, même si leurs valeurs peuvent être modifiées en cours de simulation.
Remarques :
- Dans sa spécification, un même démon instance de DescValueSpec peut comporter des réactions à des événements divers (accès, modification de valeur) sur le descripteur auquel il sera attaché.
void App_DefineMonitors() { CurrentLevelMonitor = new FloatDescValueMonitor("currentLevelMonitor"); CurrentLevelMonitor->AssignWhenGetFloatMethod(CurrentLevel_whenGet); CurrentLevelMonitor->AssignWhenSetFloatMethod(CurrentLevel_whenSet); ... };- Un même démon peut être attaché à plusieurs descripteurs différents. C'est bien clair lorsqu'il s'agit de descripteurs de même classe, attachés à différentes instances de la même classe d'entités. C'est aussi vrai pour des descripteurs de classes différentes, à condition que l'effet de bord de la fonction ait un sens identique pour les différentes classes. Par exemple, un démon dont l'effet de bord est un changement d'unité métrique, de mètres en yards, lors de l'accès à la valeur, pourra être attaché à tout descripteur ayant le sens d'une mesure en mètres, quelle que soit la classe de l'entité décrite.
Cuve::Cuve() { ... Descriptor* pD = new NiveauCourant(); CurrentLevelMonitor->AttachToDescriptor(this, NIVEAU_COURANT); ... } Tank::Tank() { ... Descriptor* pD = new CurrentLevel(); CurrentLevelMonitor->AttachToDescriptor(this, CURRENT_LEVEL); ... }- Il n'est pas possible d'attacher plusieurs démons au même descripteur (dans cette éventualité, c'est le dernier démon attaché qui reste le seul attaché). Si l'idée d'attacher plusieurs démons était justifiée par la multiplicité des effets de bords à déclencher, alors le codage de ces différents effets doit être assemblé dans les fonctions liées aux méthodes prédéfinies d'un seul démon.
Cuve::Cuve() { ... Descriptor* pD = new NiveauCourant(); FromMeterToYardMonitor->AttachToDescriptor(this, NIVEAU_COURANT); // inopérant CurrentLevelMonitor->AttachToDescriptor(this, NIVEAU_COURANT); ... } void App_DefineMonitors() { CurrentLevelMonitor = new FloatDescValueMonitor("currentLevelMonitor"); CurrentLevelMonitor->AssignWhenGetFloatMethod(CurrentLevel_otherWhenGet); ... }; float CurrentLevel_otherWhenGet(MonitorMethod* pM) { Descriptor* pVD = pM->GetDescriptorArgValue(MONITOREDDESCRIPTOR_ARGUMENT); float candidateValue = pM->GetFloatArgValue(CANDIDATEFLOATVALUE_ARGUMENT); if(candidateValue > (float)20.) { // une action corrective ou d'accompagnement } ... return candidateValue * (float)1.09361; // conversion en yards }- On peut vouloir accéder à la valeur d'un descripteur ou la modifier, sans déclencher les effets de bord du démon attaché au descripteur. Il suffit pour cela d'utiliser les méthodes normales d'accès et de modification (SetValue, GetIntValue, GetFloatValue, ) avec l'argument supplémentaire FALSE. Par exemple :
pMyInstance->GetFloatValue(MY_DESC, FALSE);- Il est possible d'ôter une capacité de réaction à un démon, en lui envoyant un message approprié, correspondant à l'événement visé : par exemple UnassignWhenGetFloatMethod, sans argument, pour ôter la réaction à l'accès à une valeur flottante :
pADescMonitor->UnassignWhenGetFloatMethod();- De même, il est possible de détacher un démon d'un descripteur en envoyant au démon le message DetachFromDescriptor, avec l'adresse de l'entité et le symbole de classe du descripteur en arguments :
pADescMonitor->DetachFromDescriptor(pMyInstance, MY_DESC);