See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: [help]question C++  (Read 2379 times)

0 Members and 1 Guest are viewing this topic.

Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
19 March 2007, 09:23:07


J'ai mis dans mon code une condition "UNMANNED" lue à partir du scenario, en relation avec une modification de FLAG
de certains groupes du mesh afin de rendre les passagers visibles ou non:
Quote
void LTV::SetPassengerVisuals ()
{ if (!vesselmesh) return;   
   static int astroidx[12] = {23,24,26,27,30,32,34,35,36,38,255,256};   
   for (DWORD i = 0; i < 12; i++){   
   if (nopsngr == 1) {     
      oapiMeshGroup (vesselmesh, astroidx[ i ])->UsrFlag |= 0x00000002;           
   } else
      {                
      oapiMeshGroup (vesselmesh, astroidx[ i ])->UsrFlag |= 1;
      }
   }
}
   
Plus tout ce qui est nécessaire pour lire et écrire dans le fichier scénario.

Çà marche bien. Si la ligne "UNMANNED" est présente, les groupes composant les astronautes sont invisibles (Flag
0x00000002). Si elle n'est pas présente, les astros sont de retour.
Mais j'aimerais également rendre possible la modif par une touche (avec le mesh mis à jour donc pendant la simu).
j'ai simplement mis:
Quote
case OAPI_KEY_F10:
   {  if (nopsngr == 0)
         {nopsngr = 1;}
                       else { nopsngr = 0; }
   return true;
   }

Mais si çà modifie bien la valeur de nopsgnr (vérifié par la présence ou non de "UNMANNED dans le current state.scn),
çà ne met pas pour autant mon mesh à jour. Je ne vois pas trop comment faire.

Pas plus de succès avec:
Quote
case OAPI_KEY_F10:
   {  if (nopsngr == 0)
         { nopsngr = 1;
                         SetPassengerVisuals () }
                       else { nopsngr = 0;
                                 SetPassengerVisuals () }
   return true;
   }


Quelqu'un sait-il comment je dois procéder?



Message modifié ( 19-03-2007 10:18 )

------------

no matter.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #1 - 19 March 2007, 13:03:45
D'abord simple truc tu peut ecrire nopsngr=!nopsngr; ca inverse le flag  aussi bien.

Secondo pour ca : "static int astroidx[12] = {23,24,26,27,30,32,34,35,36,38,255,256};"
Je te conseille vivement de passer au truc avec le MeshHeader.h que je t'avais indiqué.

Ca aucune chance que ca marche evidemment vu que tu ne change pas le flag du mesh
mais seulement un valeur a toi qui n'a aucune relation avec le mesh:

Quote
case OAPI_KEY_F10:
{ if (nopsngr == 0)
{nopsngr = 1;}
else { nopsngr = 0; }
return true;
}


Ca oui: (mais ca ne marchera pas non plus sans quelques ajouts voir plus bas)

Quote
case OAPI_KEY_F10:
{ if (nopsngr == 0)
{ nopsngr = 1;
SetPassengerVisuals () }
else { nopsngr = 0;
SetPassengerVisuals () }
return true;
}


Ca c'est bizarre et pas safe du tout:

Quote
oapiMeshGroup (vesselmesh, astroidx[ i ])->UsrFlag |= 0x00000002;



D'abord le handle du mesh visual n'est pas forcement valide il est volatil suivant le contexte
c'est peut être le probleme, si tu a plusieur vaisseaux ou que tu appuie la touche quand ton
vaisseau est "hors caméra" (hors de portée donc le visuel n'existe pas) ca va planter vu que
le handle pointe sur un truc qui n'existe plus ou alors ca ne va rien faire si tu prend le handle
de loadmeshglobal vu que ce n'est pas ce mesh la qui est affiché mais une copie
en mémoire qui est instanciée chaque fois que le visuel est crée (change camera, eloigne/raproche etc etc)
Ca marche la premiere fois car tu change le mesh avant ca copie mais en directe (F10) ca ne marche
pas car tu modifie le mesh global est pas celui qui est affiché.




Je te conseille donc les choses suivante:

Il faut que tu derive deux fonctions:

clbkVisualCreated (VISHANDLE vis, int refcount)
clbkVisualDestroyed (VISHANDLE vis, int refcount)


Dans la premiere tu obtient le handle du mesh visuel courant (la copie)
Cette fonction est appelée quand le VISUEL est crée. (le vaisseau
à affiché) donc au début de la simu, quand tu switch de vaisseau, etc etc ca garanti que
tu a toujours le dernier handle sur le mesh qui est visible.

Quote
void LTV::clbkVisualCreated (VISHANDLE vis, int refcount)
{
vesselmesh= GetMesh (vis,0);
}


Le deuxieme parametre de GetMesh est le no de mesh (loadmeshglobal(0,"") dans le genre quoi,
regarde la doc Orbiter)

Quand ton vaisseau passe hors de portée (quand tu switch ou est trop loin) il faut evidemment
detruire ce handle car il n'est plus valide donc:

Quote
void LTV::clbkVisualDestroyed (VISHANDLE vis, int refcount)
{
vesselmesh= NULL;
}


Ensuite pour changer le mesh de state je te conseil de te faire une fonction
utilitaire membre de ta classe comme ci-dessous, c'est beaucoup plus safe.

Quote
/////////////////////////////////////////////////////////////
// SetMeshPartVisible
/////////////////////////////////////////////////////////////
void LTV::SetMeshPartVisible(int Group,BOOL Visible)
{
   if(!vesselmesh)
      return;
   MESHGROUP *Mshgrp=NULL;
   if(Visible==TRUE)
   {
      Mshgrp=oapiMeshGroup(vesselmesh,Group);
      if(Mshgrp)Mshgrp->UsrFlag &= 0xFFFFFFFC;
   }
   else
   {
      Mshgrp=oapiMeshGroup(vesselmesh,Group);
      if(Mshgrp)Mshgrp->UsrFlag |= 0x00000003;
   }
}


Et tu modifie ta fonction pour changer le visuel du mesh:

Quote
void LTV::SetPassengerVisuals ()
{
          if(!vesselmesh)
   return;
          static int astroidx[12] = {23,24,26,27,30,32,34,35,36,38,255,256};
          for (DWORD i = 0; i < 12; i++)
         {
               SetMeshPartVisible(i,nopsngr);
         }
}


Voila, tout ca c'est impec mais ca ne marchera pas quand ton vaisseau n'est pas visible
ou quand ta caméra n'est pas focusée sur ton vaisseau. (visuel pas créer)
Il faut encore que tu rajoute SetPassengerVisuals dans clbkVisualCreated
comme ca quand le visuel est crée les groupes seront bien re-rafraichi comme tu veux
en fonction de la valeur nopsngr.

donc:

Quote
void LTV::clbkVisualCreated (VISHANDLE vis, int refcount)
{
vesselmesh= GetMesh (vis,0);
SetPassengerVisuals ();
}


Et evidemment il faut toujours changer ton flag avec F10:

Quote
case OAPI_KEY_F10:
nopsngr = !nopsngr ;
SetPassengerVisuals ();
return true;




Hope it help ? si c'est pas clair dis moi....

Dan



Message modifié ( 19-03-2007 14:12 )


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #2 - 19 March 2007, 13:32:28
Ahh dernière chose, vesselmesh doit être un handle différent de celui retourné
dans loadmehsglobal, un handle temporaire quoi, donc dans le h.

MESHANDLE vesselmesh; // celui utilisé par "setvisual", temporaire et change pendant le runtime.
MESHANDLE vesselmeshglobal; // celui retourné par "global" si tu le veux

moi je l'ai appelée:

hVesselMeshVisual;

Et bonne habitude SURTOUT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Dans SetClassCaps met les handle a zéro sinon plantée mystérieuse en vue:

Quote
SetClassCaps (FILEHANDLE cfg)
{
vesselmesh=NULL;
}



Passé l'init AUCUNE valeur ne devrait être indéfinie dans aucun programme, même si des fois c'est inutile
vaut mieux trop le faire qu'en oublier une qui nous fera passer des heures "d'arrache cheveux".
(c'est du vécu) ;)

Dan



Message modifié ( 19-03-2007 13:41 )


Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
Reply #3 - 19 March 2007, 14:24:59
Ok, merci Dan, je regarde çà depuis un petit moment... :siffle: Je ne comprend pas tout à 100% mais çà devrait aller.

------------

no matter.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #4 - 19 March 2007, 15:07:11
Efefctue pas a pas et ca va marcher, je t'explique le principe ce sera encore plus clair:

Orbiter load ton mesh dans une zone mémoire assez lente (mémoire pc).

Quand il l'affiche il fait une copie des données du mesh en zone graphique plus rapide
et utilise cette copie pour l'affichage, il y a autant de copie que de mesh AFFICHE
a l'ecran donc si tu a deux LTV en vue tu a deux copie de meshs different.
(C'est aussi ce qui permet d'avoir des vaisseaux avec des skin différents
ou des groupes visible de mesh différent (Deux DGIV visible l'un avec 3 astronautes l'autre avec 2 )

Toi tu modifie le flag de ton mesh globale. Au chargement, il sera copié avec
cette modif (vu que l'affichage (donc copie du mesh) demarre après le chargement du scn) donc ca marche.

Quand tu fait F10 tu modifie le mesh global mais ce n'est pas celui ci qui est utilisé
pour l'affichage, c'est la copie (instance) en mémoire. donc aucun changement.
Je suis près a parier que si tu t'eloigne jusqu'a le faire disparaitre et te rapproche
de nouveau le changement sera affiché. (eloignement= destruction de l'instance
du mesh en mémoire, raprochement, copie de nouveau effectuée depuis le mesh
global que tu a modifié avec F10)

Voila, le code vise a modifier le mesh copié en mémoire (si il existe sinon on ne modifie que ta
variable d'etat d'equipage) et à refaire le même changement si la mémoire à été detruit et
recopiée. (a la création du visuel donc copie en mémoire le flag du mesh est rafraichi suivant
ta variable)

Ch'est plus clair ?

Dan



Message modifié ( 19-03-2007 15:18 )

« Last Edit: 19 March 2007, 17:22:56 by DanSteph »

Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
Reply #5 - 19 March 2007, 15:32:13
Oui, çà va mieux ;) je comprend le fonctionnement, je vais pas tarder à tenter de compiler.
MESHGROUP *Mshgrp=NULL; c'est pour que Mshgrp ne soit pas indéfini? MESHGROUP?


« Last Edit: 19 March 2007, 17:22:56 by no matter »
------------

no matter.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #6 - 19 March 2007, 16:18:21
Quote
no matter a écrit:
Oui, çà va mieux ;) je comprend le fonctionnement, je vais pas tarder à tenter de compiler.
MESHGROUP *Mshgrp=NULL; c'est pour que Mshgrp ne soit pas indéfini? MESHGROUP?


oui oapiMeshGroup retourne un pointeur MESHGROUP et "NULL" c'est une habitude
compulsive de toujours intialiser les valeurs et surtout les handles a zéro.
Probablement inutile ici vu qu'elle est forcement définie dans oapiMeshGroup.

Mais c'est comme le clignotant. A force de le mettre même la ou ce n'est pas forcement
indispensable on ne l'oublie jamais, ca devient une habitude très saine.
(et ca ne bouffe aucun cycle proc)

La laxisme dans le code ce voit rarement en début de projet, plutôt quand on commence
à taper dans les dizaines de milliers de lignes et en général ca donne des bugs super
vache, très dur à cerner car intermitent. Sans init systématique des handle (MESHGROUP *Mshgrp=NULL; )
les protections if(Mshgrp!=NULL) ne marchent plus car ton handle non initialisé a 99.99% de chance
d'avoir une valeur indéfinie plutôt que zéro (cas si MESHGROUP hMyHandle; ).
Encore plus vache: en debug toutes les variables sont mise a zéro, ca marche. En release non,
et hop, a taaaable, CTD au menu juste quand tu avais fini ton projet. (encore pire, tu la
releasé juste après et la c'est le publique qui ce mange des CTD en cascade et te remercie ;)

Note que la fonction est safe si oapiMeshGroup return 0 (handle invalide pour toutes sorte
de raison) Orbiter ne plantera pas, il passera par dessus: (une bonne habitude qui découle de la précédente,
ne jamais utiliser de handle sans l'avoir checké avant )

Quote
Mshgrp=oapiMeshGroup(vesselmesh,Group);
if(Mshgrp)Mshgrp->UsrFlag &= 0xFFFFFFFC;


A++

Dan



Message modifié ( 19-03-2007 16:31 )

« Last Edit: 19 March 2007, 17:22:56 by DanSteph »

Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
Reply #7 - 19 March 2007, 16:38:41
Quote
void LTV::SetPassengerVisuals ()
{
if(!vesselmesh)
return;
static int astroidx[12] = {23,24,26,27,30,32,34,35,36,38,255,256};
for (DWORD i = 0; i < 12; i++)
{
SetMeshPartVisible(i,nopsngr);
}
}

Çà m'a fait réfléchir un petit moment mais j'ai compris, SetMeshPartVisible(astroidx[ i ],nopsngr); sinon ce ne sont pas les bon groupes qui sont modifiés mais les 12 premiers du mesh.
Module compilé et qui marche à 100% merci Dan :top:



Message modifié ( 19-03-2007 16:40 )

« Last Edit: 19 March 2007, 17:22:56 by no matter »
------------

no matter.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #8 - 19 March 2007, 17:22:56
Quote
no matter a écrit:
Çà m'a fait réfléchir un petit moment mais j'ai compris, SetMeshPartVisible(astroidx[ i ],nopsngr); sinon ce ne
sont pas les bon groupes qui sont modifiés mais les 12 premiers du mesh.
Module compilé et qui marche à 100% merci Dan :top:

Ooops désolé j'ai fait ca à l'arrache genre pseudo code... Mais ca marche donc :top:

Dan

« Last Edit: 19 March 2007, 17:22:56 by DanSteph »