Board index FlightGear Development Nasal

Changing model textures

Nasal is the scripting language of FlightGear.

Changing model textures

Postby FranzyG35 » Tue Nov 24, 2020 7:52 am

Hello,

I'd like to modify the texture of objects according to a property (in their own property tree like their altitude or their speed or whatever)
I tried to adapt M1 abrams bombable tank code but I don't want the objects to be in a scenario as I want to create them programmatically (many).
My problem is in fact that the nasal of the objects doesn't execute - cmdarg().getPath() doesn't give anything.

Thanks for your help.

Franck

First I create a "trigger" object placed in the scenery stg file like :

OBJECT_STATIC Models/trigger.xml -157.943 21.326 5.8
(it is a simple square that sits on the ground)

By clicking on it I create a few objects dymamically and I want to have their texture modified according to a parameter value in their own property tree

----------------------------------------
trigger.xml looks like :

<?xml version="1.0" encoding="iso-8859-1"?>
<PropertyList>
<path>square.ac</path>
<animation>
<type>pick</type>
<object-name>trigger</object-name>
<visible>true</visible>

<action>
<button>0</button>
<repeatable>false</repeatable>

<binding>
<command>property-assign</command>
<property>sim/model/start</property>
<value>1</value>
</binding>

</action>
</animation>
<nasal>
<load><![CDATA[

a loop waiting for the click : ("sim/model/start" == 1)

then here are a few places where to create the objects

places = {
{ -157.943, 21.3259, 5.67358 }
{ -157.943, 21.3259, 5.63981 }
{ -157.943, 21.3259, 5.61555 }
{ -157.943, 21.3261, 5.67633 }
{ -157.943, 21.3261, 5.67569 }
};

# Creation of 5 new objects using lng lat and alt in the places table
# These objects appear in the "ai/models" branch of the property tree
ai/model/ship[i]/texture-path=...
ai/model/ship[i]/position/... etc
# as well as the "models" branch (path = AI/Aircraft/Square/Square.xml
elevation-ft-prop = ...)
...
Here I make their altitude vary, and I want to modify their texture along with this property.
(it would be nice to write a text too - like the altitude in ft on top of them)


These objects are very basic squares coded as below

]]></load>
</nasal>

</PropertyList>

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

<?xml version="1.0" encoding="iso-8859-1"?>

<PropertyList >

<path>square.ac</path>

<animation>
<type>material</type>
<object-name>Square</object-name>
<texture-prop>texture-path</texture-prop>
</animation>

<nasal>
<load><![CDATA[

var update_my_color = func (theAlt) {

var objNodeName = cmdarg().getPath();
var node = props.globals.getNode (objNodeName);
if (theAlt > 10)
node.getNode("texture-path", 1).setValue("red.png");
else
node.getNode("texture-path", 1).setValue("blue.png");
}

# every second I modify the color of this object accordingly with its current altitude
settimer (func { update_my_color (objNodeName. getValue (altitude) }, 1);

]]></load>

</nasal>

</PropertyList>
----------------------------------------
FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby Hooray » Tue Nov 24, 2020 9:04 am

Hi & welcome !

Since you mention changing textures and writing text onto them, you'll probably want to check out the Canvas system:

Image

http://wiki.flightgear.org/Canvas_Snippets
http://wiki.flightgear.org/Howto:Dynami ... via_Canvas

The model manager/AI system can also be scripted to set up different models/flights without having to go through the AI/scenario system:

Image

http://wiki.flightgear.org/AI_Scenery_Objects
http://wiki.flightgear.org/Ground_Services

If you are specifically interested in missions/adventures, see: http://wiki.flightgear.org/Missions





PS: You might want to use the code tags to post your code
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Changing model textures

Postby FranzyG35 » Wed Nov 25, 2020 12:49 am

Hi,

Thank you Hooray for the quick and very interesting answer.

Looking at the canvas concept, it seems very adequate to my need for putting dynamic text on my objects,
although I'm not sure yet how to put a canvas on an object in the landscape, all I see for now in the snippets,
is mostly regarding dialogs, hud, or aircraft features in (x,y) coordinates. I'll look more in depth into it.
For now, I'm still not sure how to code the modifying of a texture of one surface of an .ac model known as a "name" in an xml file.

The main question that remains unsettled is the fact that my nasal <load> code </load> is not run when I create a new AI object dynamically.
Wouldn't this prevent to dynamically stick various canvasses on this object too.
There must be something I miss : what are the conditions/circonstances that run this nasal code normally - allowing
the new AI object to access it's property tree members and changes it's visible texture accordingly.
It surely does when it's an "entry" in a scenario : are these "entries" registered somewhere else ?

By the way when I say "creating a object" I mean adding a branch in the property tree in ai/models and one in models, like they do in bombable - it's enough to show the object in the landscape and have it move properly. I'm afraid it's not enough to run the nasal load section of the xml of the object.

Thanks for your further helping me.

Franck
FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby wlbragg » Wed Nov 25, 2020 1:10 am

What about the "addon" framework. It is very flexible and powerful. See Cargo Towing and Red Griffin ATC among others for examples of what is capable.
Cargo Towing is a great example because it handles many of the concepts your working on like introducing and interfacing with scenery objects and manipulation of the same. There is a wealth of concepts explored in just those two addons alone.

The DaSH Human powered aircraft has a small Challenge feature that explores some of what you are trying to do. The Shuttle also has many examples of AI models being introduce to the scene and manipulation of the same.
The c172p also has the exterior aircraft check out code that might give you some insight. All of these examples work with many of the principles your looking for I think.
Kansas and Ohio/Midwest scenery development.
KEQA, 3AU, KRCP Airport Layout
Intel i7/GeForce RTX 2070/Max-Q
User avatar
wlbragg
 
Posts: 7588
Joined: Sun Aug 26, 2012 12:31 am
Location: Kansas (Tornado Alley), USA
Callsign: WC2020
Version: next
OS: Win10/Linux/RTX 2070

Re: Changing model textures

Postby FranzyG35 » Tue Dec 01, 2020 6:39 am

Hello Hooray,

It was hard work to switch to canvasses and go through all these links you gave.
But the problem remains.

After all, my nasal program (in the trigger.xml) produces adequate canvasses for each model.
I can see them in (debug) control boxes and they're correct with various texts and textures, but they don't show up on the models surfaces. ( Placement No Match status )

See details below. Please let me know if you want the nasal code.

Franck


My ac file (which I use for all models) is rather simple :

AC3Db
MATERIAL "blue" rgb 0.000 0.000 1.000 amb 0.800 0.800 0.800 emis 0.000 0.000 0.000 spec 0.500 0.500 0.500 shi 64 trans 0.000
OBJECT world
name "Blender_exporter_v3.0__plan.ac"
kids 1
OBJECT poly
name "mySurface" (xxxxxx)
data 5
Plane
texture "myTextures/red.png" (******)
texrep 1 1
crease 40.0
numvert 4
-30.66423 0 30.35963
30.66423 0 30.35963
-30.66423 0 -30.35963
30.66423 0 -30.35963
numsurf 1
SURF 0X0
mat 0
refs 4
0 0 0
1 1 0
3 1 1
2 0 1
kids 0

All the objects appear with the "myTextures/red.png" (******) instead of the one I define in the declaration of my canvas (no text of course)

m.myCanvas.addPlacement ({ "node" : "mySurface" }); (xxxxxx)

In the property tree I read :

/canvas/by-index/texture[i]/placement
node = 'mySurface' (string)
status-msg = 'No match' (string)
/canvas/by-index/texture[i]/placement[1]
id ='xxx' (string)
status-msg = 'Ok' (string)
type = 'window' (string)
FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby gordonshamway23 » Thu Dec 03, 2020 10:04 pm

Can you possibly show us your canvas creation code, maybe there is a problem?
Looking at c++ code real quck, "no match" status means the canvas is not attached on your model.
Can you confirm, the addPlacement method was actually called? Perhaps by adding a

Code: Select all
gui.popup("addPlacement has been called :)");


statement before your call.
gordonshamway23
 
Posts: 24
Joined: Sun Nov 22, 2020 8:15 pm

Re: Changing model textures

Postby Hooray » Thu Dec 03, 2020 10:50 pm

please post a self-contained snippet of code that people can execute via the Nasal console, referencing 3D models/textures that are part of the base package, so that we're able to reprodue the issue and can help you.

PS: And please consider using code tags for your snippets when posting (5th button from the left above the edit area)
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Changing model textures

Postby FranzyG35 » Fri Dec 04, 2020 1:14 am

Hello

Thank you very much for your help :D

Please find the code below
I know it's a bit too long for a snippet but it should be nice for a demo :
I add the nasal part of trigger.xml in another post - as it overshoots the limit


Assuming you have the PHNL scenery installed :
1- Add this line to the w160n20/w158n21/367568.stg
OBJECT_STATIC Models/FUN/trigger.xml -157.927 21.3141 4 45
2- in FGDATA/Models/ create a FUN directory
where to put the code below into a trigger.xml file
add the model file as plaque.ac
Add a subdirectory called "TexturesPlando" and place the bombable textures red[i].png and camo[i].png

3- Start flightgear in PHNL RWY O4R with any aircraft
change the view with "V" and a couple of ctrl-Xes and position high above the aircraft
4- You'll see a red square on the RWY : click on it
5- Now you have 10 seconds to move the 5 dialogs anywhere you want (as they pileup in the left corner)


You'll see the changes of texture and text in the dialogs as the models appear and move :)



Now the issue I've been trying to solve is that the textures and text of the models
do not change accordingly as they should.
Look for the $$$$$$$$ string in trigger2.xml to locate the instruction below
m.myCanvas.addPlacement ({ "node" : "mySurface" });
mySurface corresponds to the face description in the ac model from plaque.ac :
name "mySurface"


The / key allow to check the canvas branch of the property tree
starting from texture[3] with the "placement" set to "No Match"
Please take a look at the model branch showing the data of each model
as well as the ai/Models/ship[i] containing the ai data of the models including my debug traces


plaque.ac :
Code: Select all
AC3Db
MATERIAL "bleu" rgb 0.000 0.000 1.000  amb 0.800 0.800 0.800  emis 0.000 0.000 0.000  spec 0.200 0.200 0.200  shi 64 trans 0.000
OBJECT world
name "Blender_exporter_v3.0__plan.ac"
kids 2
OBJECT poly
name "mySurface"
data 5
Plane
texture "TexturesPlando/red.png"
texrep 1 1
crease 40.0
numvert 4
-2.66423 0 2.35963
2.66423 0 2.35963
-2.66423 0 -2.35963
2.66423 0 -2.35963
numsurf 1
SURF 0X0
mat 0
refs 4
0 0 0
1 1 0
3 1 1
2 0 1
kids 0


trigger.xml (1st part) :
Code: Select all
<?xml version="1.0" encoding="iso-8859-1"?>

<PropertyList>
   
    <path>plaque.ac</path>

    <animation>
        <type>pick</type>
        <object-name>mySurface</object-name>
        <visible>true</visible>

        <action>
            <button>0</button>
            <repeatable>false</repeatable>

            <binding>
                <command>property-assign</command>
                <property>sim/model/startTheShow</property>
                <value>1</value>
            </binding>

        </action>
    </animation>
FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby FranzyG35 » Fri Dec 04, 2020 1:22 am

Thanks for pasting this at the end of trigger.xml
I'll need a 3rd post as this code is still too big) :oops:


trigger.xml (part 2/3) :
Code: Select all
<nasal>
    <load><![CDATA[

        print ("*************** Hi from trigger.xml !");

        var sortir = 0;    # rester dans la boucle tant qu'on n'a pas cliqué sur le barrage

        var self = cmdarg();

        setprop ("sim/model/startTheShow", 0);

        if (getprop ("sim/model/startTheShow") == 0) {
            gui.popupTip ("Click the square please !");
        }
       
        var loopid = 0;

        #=============================================
        # declaration de la fonction a appeler par le timer

        var loop = func (id) {

            id == loopid or return; # signifie : id vaut loopid sinon on arrête (on sort du programme loop)
                                    # donc on sort si loopid est modifie dans ce programme et passe a 1
                                    # sortie de la boucle en cas de unload

            if (getprop ("sim/model/startTheShow") == 1) {

                setprop ("sim/model/startTheShow", 2); # only one click

                gui.popupTip (" Started !");
               

        # ======================================================
        # fonctions variables et constantes :

        # Table des objets crees       
        var myPlando = {};


        # ========= Canvas =============
       
        # creation d'un hash avec les textures affichables - hash with all images added
        var layers = {};
       
        # definition de la racine des canvasses (dans l'arbre des proprietes)
        var canvasRoot = "";
       
        # ========= fin Canvas =========
       
        #===
        # function to get the ground altitude (in feet) of a given lat/lon position
       
        var feet2meters=.3048;
       
        var getAltitude = func (lat, lon) {

            var info = geodinfo (lat, lon);
           
            if (info != nil) {
                var alt_m = info[0];
                if (alt_m == nil) alt_m = 0;
                return alt_m/feet2meters; #return the altitude in feet
            } else  return 0;
           
        }
        #============

        var AltLacBarrage = 7;

       
        # from 367568.stg (trigger model position)
        # OBJECT_STATIC Models/0Barrage/trigger2.xml -157.9274115157485  21.31382377860803 4  45
       
        var SoftAlt  = 6;
        var CurrLat  = 21.3141;
        var CurrLon  = -157.927;
        var HDG_START = 45;
       
        #============
        # Constantes du systeme (mise au point/affinage du comportement)
        #============

        # le modele utilise pour representer une masse d'eau individuelle

        # var modelVariable = "Models/0Barrage/plan_d_eau_rouge.ac";
          var modelVariable = "Models/0Barrage/plaque.ac";
        # var modelVariable = "Models/0Barrage/plan_d_eau_rouge3D.xml";
       
        LARGEUR_MODELE = 5.0;
       
        var NUMERO_INITIAL_DE_PLANDO = 1;
        var noPlando = NUMERO_INITIAL_DE_PLANDO;   # numero d'ordre de creation des plandos - indice sur myPlando
       
        var ID_BARRAGE = 1;  # confusion : indice plando barrage : il y aura un probleme quant le barrage sera constitue de plusieurs plando
                             # utiliser plutot un flag specifique : 1 : je fais partie du barrage, 0 : non
 
        # indices dans la table myPtrs
       
        var   K_AMONT = 0;   # constante indice pointeur sur le pere
        var   K_AVAL  = 2;   # constante indice pointeur sur le fils
        var   K_LEFT  = 3;   # constante indice pointeur sur le voisin de gauche
        var   K_RIGHT = 1;   # constante indice pointeur sur le voisin de droite

        var  headAngle = [180, 90, 0, 270];  # table des angles des rotations a effectuer pour trouver l'amont, l'aval, la droite ou la gauche
                                            # indicee par les K_*
                                           
        var tabCorrDirs = [2, 3, 0, 1];     # correspondances pour myPtrs[] : a gauche pour le pere signifie a droite pour le fils
                                            #                                 en bas pour le pere signifie en haut pour le fils
                                            # permet de conserver l'orientation des plandos
       

        # Mise en service de la gestion du debit : 1
        # on va donc utiliser les parametres suivants DEBIT_BARRAGE_TIMEOUT et RATIO_DECROISSANCE
        spreadEnabled = 0;
       
        var MET_DE_L_HUILE = 5;         # + 5 + 5 + 10  : rajouter un petit quelque chose met toujours de l'huile, Enfin pas toujours...
                                        # des fois c'est de l'eau - comme ici ! et ca coince, ca grippe, ca rouille !!!!

        var DEBIT_BARRAGE_TIMEOUT = 5;  # en secondes : valeur du timeout entre appels du checkMyEnvironment par le barrage
                                        # la modification de cette valeur permet de regler le debit par la breche du barrage
                                        # diminuer le to revient a augmenter le debit !!!

        var  RATIO_DECROISSANCE = 0.88 ; #  0.66 1 0.5 0.25 0.33;   # rapport altitude niveau haut et niveau bas d'une cascade :
                                        # le plando niveau bas est au tiers de la hauteur du plando haut
                                        # caracteristique du liquide aqueux
                                        # ici les matheux pourront integrer l'equation differentielle de Navier Stokes - je leur laisse
                                       
        if (spreadEnabled == 0) {
            RATIO_DECROISSANCE = 1;
            DEBIT_BARRAGE_TIMEOUT = -1;
        }
               
        var WATERSPEED = 36;            # vitesse des plandos (kts) : caracteristique du liquide aqueux
                                        # peut etre module par la pente
        var WATERVSPEED = 0.33;         # vitesse de montee / descente du niveau                     
                       

        # types d'appel de checkMyEnvironment
        var   SPREAD         = 0;   # changement de niveau d'un plando : il appelle ses voisins pour les prevenir
        var   END_OF_TRIP    = 1;   # fin de trajet d'un plando : il s'appelle lui meme


#============
# classe plando
#============
   
var plando = {

        # ======== TRACES
        petitCompteur : 0,  # utilise pour les traces stockees dans l'arbre : permet de stocker les traces dans leur ordre chronologique
                            # dans l'arbre des proprietes : autrement, comme elles sont classees par ordre alphabetique, on ne peut rien comprendre

        tracer : func (msg, prio = 0 )  {
       
            if (prio != 5) return;  # gestion des niveaux de trace seules les traces de niveau x sont inserees dans les modeles dans l'arbre
           
            me.petitCompteur += 1;
            var  txtinfo = "information";
            if (me.petitCompteur > 999 ) return;          # apres ca fait peter le stack et on ne voit plus le debut
           
            else if (me.petitCompteur < 10 ) txtinfo ~= "00";  # ajouter 0 pour les 9 premiers sinon ils sont noyes dans les autres
                                                         # (les branches de l'arbre sont classees par ordre alphabetique)
            else if (me.petitCompteur < 100 ) txtinfo ~= "0";
               
            me.ai.getNode (txtinfo~me.petitCompteur, 1). setValue (msg);
        },
       
        tracer_m : func(msg)  {
            me.petitCompteur += 1;
            me.ai.getNode ("information"~me.petitCompteur, 1). setValue (msg);
        },
       
        traceIn : func(typeOfCall, indiceAppelant)  { # *** traces infos d'entree de checkmyenvironment
                     var colll = "";
             if (typeOfCall == END_OF_TRIP)  colll = "END_OF_TRIP";
        else if (typeOfCall == SPREAD)  colll = "SPREAD";
        me.tracer ( "=============="~colll~" :  appelant=" ~ indiceAppelant ~ " moi="~int(me.mySoftAlt)~" semaphores:["~me.pas_fini ~" "~me.moving ~" "~me.movingH~"]", 5);


            # ----
            # les valeurs entieres serait plus pratiques :  int (appelantSoftAlt) Ca marche !!!
           
            var autoappel = "AUTOAPPEL";
            if (indiceAppelant != me.myIndice) autoappel = "appel par "~indiceAppelant;

        #    me.tracer ("CHECK : " ~autoappel, 5);
            var ptrx = " "~me.myPtrs [0]~" "~me.myPtrs [1]~" "~me.myPtrs [2]~" "~me.myPtrs [3]~" ";
        #    me.tracer ("check : pointeurs ="~ptrx~"=", 5);
        #    me.tracer ("HARD me:"~int (me.myHardAlt)~"   "~int (me.theHardAlt[0])~" "~int (me.theHardAlt[1])~" "~int (me.theHardAlt[2])~" "~int (me.theHardAlt[3]), 5);
        #    me.tracer ("SOFT me:"~int (me.mySoftAlt)~"   "~int (me.theSoftAlt[0])~" "~int (me.theSoftAlt[1])~" "~int (me.theSoftAlt[2])~" "~int (me.theSoftAlt[3]), 5);
                   
           
            # ----
            # *** fin traces infos d'entree
        },
       
        traceOut : func()  {
       
            # *** traces de sortie de checkmyenvironment
           
                # trace des nouvelles valeurs des pointeurs apres creation eventuelle de plandos et verification des altitudes

                me.tracer ("check FIN :  "~ me.myIndice  ~ " hard ="~int (me.myHardAlt) ~ " soft="~int (me.mySoftAlt), 6);
               
                var ptrz = " "~me.myPtrs [0]~" "~me.myPtrs [1]~" "~me.myPtrs [2]~" "~me.myPtrs [3]~" ";
                me.tracer (" check FIN pointeurs : =" ~ptrz ~ "= hard:"~int (me.myHardAlt) ~ " soft:"~int (me.mySoftAlt), 5); 
                var H_alt = " "~int (me.theHardAlt [0])~" "~int (me.theHardAlt [1])~" "~int (me.theHardAlt[2]) ~" "~int (me.theHardAlt [3])~" ";
                me.tracer (" altitudes H   ="~H_alt~"=", 5);
                var S_alt = " "~int (me.theSoftAlt [0])~" "~int (me.theSoftAlt [1])~" "~int (me.theSoftAlt [2])~" "~int (me.theSoftAlt[3])~" ";
                me.tracer (" altitudes S   ="~S_alt~"=", 5);
   
            #    me.tracer ("HARD me:"~int (me.myHardAlt)~"   "~int (me.theHardAlt[0])~" "~int (me.theHardAlt[1])~" "~int (me.theHardAlt[2])~" "~int (me.theHardAlt[3]), 5);
           #     me.tracer ("SOFT me:"~int (me.mySoftAlt)~"   "~int (me.theSoftAlt[0])~" "~int (me.theSoftAlt[1])~" "~int (me.theSoftAlt[2])~" "~int (me.theSoftAlt[3]), 5);
           #     var ptrx = " "~me.myPtrs [0]~" "~me.myPtrs [1]~" "~me.myPtrs [2]~" "~me.myPtrs [3]~" ";
           #     me.tracer ("check : pointeurs ="~ptrx~"=", 5); 
           
                # ligne de presentation c'est plus chic - signalisation de la fin d'un checkMyEnvironment
                me.tracer ("==========================================", 5);
               
                # *** fin traces de sortie
        },
        # ======== fin TRACES
       
       
        # ========= Couleurs textures ============

        maj_my_color : func (waterDepth) {
       
           var   tabColors = [ "red.png", "red2.png", "red3.png", "camo.png", "camo2.png"];
           var   baseColorDir = "AI/Aircraft/plando/TexturesPlando/";
           
           # pour canvas  waterDepth n'est qu'un compteur du modele et non son altitude
           me.myImage.setFile(baseColorDir~tabColors[waterDepth]) ; # modif de la texture de mon canvas
        },
        # ========= fin Couleurs textures ============
       
        # ========
        # ==== calcul de l'altitude pres de l'objet dans une direction (évaluation du contexte - relief environnant)
       
        getHardAlt  : func ( lat, lon, heading) {
               
                if (heading > 360) heading -= 360;  # il peut se produire que le heading depasse 360 par suite d'addition d'angles
               
                # ATTENTION : se mefier : Chercher l'altitude pres de l'objet :
                # l'objet n'est pas forcement carre : devant et sur les cotes c'est pas pareil et le heading ne suffit pas
                # probleme aussi de frequence de ce calcul - le faire une seule fois par objet et par direction
                # et seulement si c'est necessaire (le calcul peut avoir ete fait pas un voisin)
                # en fait determiner l'altitude au sol de sa position finale (pour devant)
                # ou de son voisin si laterale (hdg 90 ou 270)

                var GeoCoord = geo.Coord.new();       # from Nasal library/geo  FGDATA/nasal/geo.nas
                GeoCoord.set_latlon (lat, lon);
           
                # ==== calcul de l'altitude en avant de l'objet !!!
               
                # calcul formel en fonction de la taille du modele : dims.length_m/2 + cte_m
                # ici on va dire (LARGEUR_MODELE + 10) metres devant l'objet (ou derriere ou a droite ou a gauche en fonction du cap)
               
                GeoCoord. apply_course_distance (heading, LARGEUR_MODELE + 10);
                var toFrontAlt_ft = getAltitude (GeoCoord.lat(), GeoCoord.lon() );

                return (toFrontAlt_ft);
        },
   
   
        # ====== MOTEUR : LA SUBSTANTIFIQUE MOELLE DU PROGRAMME
        # ====== moteur de gestion du comportement des plandos
        # ici sont geres : les deplacements et la creation ou non de nouveau plando et les transferts d'informations (alt) entre plandos
        # en fonction du contexte altimetrique
        #
        # methode a executer sur
        #       - fin du deplacement d'un plando sur une distance de sa largeur
        #       - chaque modification d'altitude d'un voisin ayant un impact sur moi (en tant que plando)
        #       - le debit d'une nouvelle quantite d'eau par le barrage
        #
        # parametre :
        #     typeOfCall :
        #               END_OF_TRIP   : je m'appelle moi meme en fin de deplacement pour disperser (eventuellement) l'inondation
        #               SPREAD        : un voisin m'appelle pour me signaler son altitude - qui va donc influer sur la mienne
        #                          ou si c'est le barrage qui appelle directement pour envoyer du debit (a ses enfants directs)
        #               
        #        mais ce parametre typeOfCall ne sert qu'a des fins de trace et debug
       
        G_KKK : 0,    # pour le spread, car le jjj est ecrase (G_KKK est donc une variable de travail)
       
        checkMyEnvironment : func (indiceAppelant, appelantSoftAlt, appelantHardAlt, typeOfCall) {  # appelantHardAlt inutilise
       
            # le barrage ignore les spreads venant donc de l'aval
            # if (me.myBarrageMem == 1) { if (typeOfCall == SPREAD) { return; }  }
            # ignorer les spreads dont l'altitude ne modifie rien
            # else {  if (typeOfCall == SPREAD and appelantSoftAlt == me.mySoftAlt) { return; }  }
             
            var old_alt = 0;
            var new_alt = 0;
         
            # me.traceIn (typeOfCall, indiceAppelant);
           
            if (me.pas_fini == 1) {
                # peut etre quand meme stocker l'altitude et l'indice appelant avant de degager ....  BOF pas probant
                for (var i = 0 ; i < 4 ; i+=1) {
                    if (indiceAppelant == me.myPtrs[i]) { me.theSoftAlt[i] = appelantSoftAlt; break; }
                }
               
                  me.tracer ( "================ IGNORED pas_fini "~int(appelantSoftAlt), 7);
                  return;  # pas de mise a jour pendant l'execution de checkMyEnvironment (pas de reentrance)
                }
               
            if (me.moving   == 1)  {
                #  peut etre quand meme stocker l'altitude et l'indice appelant avant de degager .... BOF pas probant
                for (var i = 0 ; i < 4 ; i+=1) {
                    if (indiceAppelant == me.myPtrs[i]) { me.theSoftAlt[i] = appelantSoftAlt; break; }
                }
                 
                  me.tracer ( "================ IGNORED moving "~int(appelantSoftAlt), 7);
                  return;  # pas de mise a jour pendant le deplacement sinon ca boucle en stack overflow
                }
         
            me.traceIn (typeOfCall, indiceAppelant);
       
            #  if (me.movingH  == 1)   {
            #         me.tracer ( "IGNORED moving", 5);
            #         return;  # pas de mise a jour pendant le deplacement sinon ca boucle en stack overflow
            #       }

            me.pas_fini = 1;  # sorte de semaphore - qui marche bien - mais il y a fatalement une perte de debit (une fuite quoi)
                              # puisqu'on jette des messages de mise a jour (donc du debit) par return
                             
            # ***
            # *** calculer ma nouvelle altitude
           
            #     *** je suis un element du barrage
            if (me.myBarrageMem == 1) {
               
                # transmettre le debit aux enfants deja crees
                for (var i = 0 ; i < 4 ; i+=1) {
   
                    if (me.myPtrs[i] > 0) {
                        me.tracer ( "DEBIT vers -> "~i~" - niveaux : hard=" ~ int(me.myHardAlt) ~ " soft="~int(me.mySoftAlt), 1);
                        if (spreadEnabled == 1) { 
                            myPlando[me.myPtrs[i]].checkMyEnvironment (ID_BARRAGE, myPlando[ID_BARRAGE].mySoftAlt,
                                                                               myPlando[ID_BARRAGE].myHardAlt, SPREAD);

                        # c'est ici que je sais combien de m3 le barrage delivre
                        # donc on va gerer le volume ici / le vidage du barrage
                       
                        var DdeltaAlt = me.mySoftAlt - myPlando[me.myPtrs[i]].mySoftAlt;
                       
                        DebitTotal += (DdeltaAlt * LARGEUR_MODELE * LARGEUR_MODELE);
                       
                        # afficher ca a l'ecran :
                        gui.popupTip ( "Debit : "~DebitTotal );   # ca ne fait rien ? warum ?
                         }
                    }
                }
           
                #  rearmer le timer qui regle le debit au niveau du barrage  : DEBIT_BARRAGE_TIMEOUT secondes
                if (DEBIT_BARRAGE_TIMEOUT > 0)
                    settimer (func { myPlando[ID_BARRAGE].checkMyEnvironment (ID_BARRAGE,
                                            myPlando[ID_BARRAGE].mySoftAlt, myPlando[ID_BARRAGE].myHardAlt, SPREAD); }, DEBIT_BARRAGE_TIMEOUT);

            }
           
            #     ***  je ne fais pas partie du barrage : je suis un plando ordinaire n'importe ou
            else {
     
           
            ### ce ne sont que des traces
                me.tracer ("CHECK : je ne suis PAS LE BARRAGE - OK - niveaux : hard=" ~ int(me.myHardAlt) ~ " soft="~int(me.mySoftAlt), 1);
                me.tracer ("CHECK : CALCUL ALT : appelant=" ~ indiceAppelant ~ " moi="~me.myIndice ~ " soft="~int(me.mySoftAlt), 1);
               
                                    var colll = "";
                        if (typeOfCall == END_OF_TRIP)  colll = "END_OF_TRIP";
                else if (typeOfCall == SPREAD)  colll = "SPREAD";
                   
                me.tracer (" "~ colll ~ " : appelant=" ~ indiceAppelant ~ " moi="~int(me.mySoftAlt), 1);

            ### fin ce ne sont que des traces
           
                old_alt = me.mySoftAlt;
                new_alt = old_alt;    # pas de modif d'altitude a priori
               
                if (indiceAppelant != me.myIndice) {  # pas de modif d'altitude si je m'appelle moi meme
               
                    # je ne m'appelle en fin de course que pour regarder les voisins (fenetre sur cour) pas pour modifier mon alt
                    # par contre si un voisin m'appelle c'est d'abord pour me signifier
                    # sa nouvelle altitude et que je recalcule la mienne : donc voila :
                   
                    # mon voisin me previent de son changement d'altitude
               
                    # ponderation avec les altitudes alentour :
               
                    var totalalt = 0;
                    var n = 0;  # nombre d'altitudes definies autour
                    for ( var i = 0 ; i < 4 ; i+= 1  ) {
                       
                        # recuperer les altitudes des voisins
                #        if (me.myPtrs [i] > 0) {                           
                #            if (me.theSoftAlt [i] != myPlando[me.myPtrs [i]]. mySoftAlt) {
                                  # probleme de coherence entre pere et fils (voir East of Eden - Jimmy Dean)
                                  # var toto = EAST_OF_EDEN; #  mais c'est juste un petit probleme de synchronisation de detail inutile de faire planter pour ca
                #                  me.theSoftAlt [i] = myPlando[me.myPtrs [i]]. mySoftAlt;
                #            }
                #        }
               
                        # normalement les alt ont ete mises a jour directement chez moi
                       
                       if (me.theSoftAlt [i] != -1) { totalalt += me.theSoftAlt [i]; n += 1; }
                      #  if (me.theSoftAlt [i] > 10) { totalalt += me.theSoftAlt [i]; n += 1; }
                    }
                   
                    # rajouter la mienne : elle compte aussi
                    totalalt += me.mySoftAlt; n += 1;
                    totalalt += me.mySoftAlt; n += 1;   # et meme beaucoup
                    totalalt += me.mySoftAlt; n += 1;   # tres beaucoup
                   
                    new_alt = totalalt / n;    # + 5 + 5 + 10  : rajouter un petit quelque chose met toujours de l'huile, Enfin pas toujours...
                                               # des fois c'est de l'eau - comme ici ! et ca coince, ca grippe, ca rouille !!!!
                   
                   # if (spreadEnabled == 0)
                        new_alt += MET_DE_L_HUILE;
                   
                   # new_alt = me.mySoftAlt;  # pas confiance dans le calcul ci dessus : plando souterrains
                                               
                    # AltLacBarrage doit etre un grand maximum pour tout plando
                   
                    if (new_alt > AltLacBarrage) { new_alt = AltLacBarrage;  }
                   
                    # autant mettre ma nouvelle altitude directement chez les voisins meme s'ils pourraient le recalculer plus loin (spread)
                    # normalement faudrait une methode pour ca, en vraie programmation objet mais bon...
                    for ( var i=0 ; i < 4 ; i+= 1  ) {
                        # maj mon altitude chez les voisins
                        if (me.myPtrs [i] > 0) myPlando[me.myPtrs [i]].theSoftAlt [tabCorrDirs[i]] =  new_alt;
                    }

                    me.mySoftAlt = new_alt;    # mise a jour de mon altitude perso
                   
                    if (me.mySoftAlt < me.myHardAlt) {
                   
                        me.tracer ("CHECK : RETRAIT : hard=" ~ int (me.myHardAlt) ~ " > soft="~int (me.mySoftAlt), 5);

                        # retrait des eaux : toute l'eau est partie on se retrouve sur le caillou
                        # Moise va pouvoir etre recupere par la princesse (cas de la rupture du barrage d'Assouan)
                        # ou Noe va pouvoir debarquer les couples d'animaux (cas de la rupture du detroit de Gibraltar)
                        # autodestruction du plando avec modif des chainages etc....
                        # il vaut mieux pas pour l'instant - ca evite de la charge CPU et surtout de se faire chier la bite
                        # le plando passe sous le sol et on ne le voit plus donc c'est bon
                       
                        # dans ce cas, autant sortir tout de suite apres maj altitude du modele
                        me.updateHeight (me.mySoftAlt);
                    #   me.update();
                   
        ############     me.pas_fini = 0;
        ############     return;
                    }
                   
                    me.tracer ("CHECK : CHG ALT : hard=" ~ int (me.myHardAlt) ~ " soft="~int (me.mySoftAlt) , 3);
                }
            }
           
            #  l'altitude visible du MODELE (dans l'arbre props/ai/models...) sera modifiee a la fin de ce programme
           
            # *** fin calculer ma nouvelle altitude : me.mySoftAlt
            # ***
           
           
            ### ce ne sont que des traces
            me.tracer ("    ***** fin calcul nouvelle altitude", 6);
            if (1) {  # pour isoler colll
                     var colll = "";

                     if (typeOfCall == END_OF_TRIP)  colll = "END_OF_TRIP";
                else if (typeOfCall == SPREAD)  colll = "SPREAD";

                me.tracer (colll ~ ": appelant=" ~ indiceAppelant ~ " old_alt :"~int(old_alt) ~ ">>>>>" ~ int(me.mySoftAlt)~ " (new_alt) $$$", 5);
            }
            ### fin ce ne sont que des traces   new_alt
           
            me.mySoftAlt += 5;      #### ACHTUNG pourquoi mySoftAlt est ecrase
           
            # ***
            # *** detection des altitudes hard autour
            #          theHardAlt[i] = -1 si on n'a pas encore detecte l'altitude dans cette direction
            # chercher les altitudes du rocher autour de moi si elles n'ont pas encore ete recherchees (determinees)
            # - pour le barrage on ne recupere rien cote lac mais on recupere bien en aval
            # a ne faire qu'une fois par plando en principe - par exemple a la fin de son positionnement definitif
           
            if (typeOfCall == END_OF_TRIP) {
           
                for (var i = 0 ; i < 4 ;  i += 1)  {               

                    var heading = HDG_START + headAngle[i];

                    if (me.theHardAlt[i] == -1) {
                       
                            # l'altitude dans cette direction n'a pas encore ete recherchee
                            # detecter le sol dans cette direction
                            # et stocker l'altitude du sol dans cette direction
                           
                            #  *** recherche de l'altitude du sol dans cette direction ***
                            me.theHardAlt[i] = me.getHardAlt (me.myLat, me.myLon, heading);
                           
                        # hypothese realiste : l'eau ne monte pas plus haut que l'altitude du lac de barrage
                            # donc les zones plus en hauteur seront inaccessibles
                            if (me.theHardAlt[i]  >= AltLacBarrage) {
                                me.tracer ("    ***** BARRAGE "  ~ " i=" ~ i ~" Alt[i]:"~int (me.theHardAlt[i])~ " hd="~heading, 1);
           #####                     me.myPtrs[i] = -3;   # declaration off limits zone
                            }
                    }
                }
               
                me.tracer ("    ***** fin calcul hardalts ",5);
                var H_alt = " "~int (me.theHardAlt [0])~" "~int (me.theHardAlt [1])~" "~int (me.theHardAlt[2]) ~" "~int (me.theHardAlt [3])~" ";
                me.tracer (" altitudes H   ="~H_alt~"=", 5);
                var S_alt = " "~int (me.theSoftAlt [0])~" "~int (me.theSoftAlt [1])~" "~int (me.theSoftAlt [2])~" "~int (me.theSoftAlt[3])~" ";
                me.tracer (" altitudes S   ="~S_alt~"=", 5);
            }
           
            # donc on a recupere les altitudes du rocher autour de moi (pour les chainages encore inexistants (par exemple devant))
            # on peut alors en deduire la pente et la vitesse pour creer des enfants dans la direction donnee
            # en deduire la duree du to pour reveil et creation des fils
            # pour l'instant on se contente de la creation des fils eventuels (on considere la vitesse comme constante)

            # *** fin detection des altitudes hard autour
            # ***

           
            me.traceIn (typeOfCall, indiceAppelant);
           
            # ***
            # *** repercussion alentour : creation de cascade/retrait/falaise
           
            # (par defaut tous les pointeurs et altitudes sont initialises a -1)

            # for (var i = 0 ; i < size (me.myPtrs) ;  i+= 1)   # size (me.myPtrs) ne marche pas,  me.myPtrs.length,  me.myPtrs.length() non plus
            for (var i = 0 ; i < 4 ;  i += 1)  {
               
                # 3 cas : - off limit, deja un plando ou pas encore de plando
               
                # ne rien faire de tel qu'une cascade  (un nouveau plan d'eau)  vers le barrage ou vers une zone interdite
                if (me.myPtrs [i] == -3) continue;  # rien faire dans le cas -3 : off limits
                                                    # j'ai l'impression que le 'continue' ne fonctionne pas comme il devrait
 
                if (me.myPtrs [i] > 0) continue;  # rien faire s'il existe deja un plando
               
                if (me.myPtrs [i] == 0 or me.myPtrs [i] == -1) {
 

                        me.theSoftAlt[i] =  me.mySoftAlt;  # j'ai un doute sur le calcul ci-dessus

                        if ( noPlando > 4 ) return;
                           
                       
                        # ****** CREATE PLANDO *********
           
                        # creer un nouveau plando
                        # on le cree au meme emplacement et il va gentiment prendre sa place finale dynamiquement en AI
                       
                        var start_alt_ft = me.altN.getValue();   # altitude actuelle : garantie de fluidite des altitudes
               
                        var heading = HDG_START + headAngle[i];     # heading de deplacement du plando
                               
                        # calcul de l'altitude finale du fils (transmission de RATIO_DECROISSANCE * epaisseur d'eau                                       
                        var goalalt = (me.mySoftAlt - me.myHardAlt) * RATIO_DECROISSANCE + me.theHardAlt[i];

                        if (goalalt > AltLacBarrage) goalalt = AltLacBarrage; # tronquer a AltLacBarrage
                        if (goalalt > start_alt_ft)  goalalt = start_alt_ft;  # l'eau descend !!! en general
                       
                        me.theSoftAlt[i] = goalalt;
                       
                        me.tracer ("===> CASCADE "~i~" xy:("~me.x~","~me.y~") myHardAlt:"
                                ~ int (me.myHardAlt) ~ " mySoftAlt:"~int (me.mySoftAlt)~" > "~int (me.theHardAlt[i])~" goal "~int (me.theSoftAlt[i]), 5);
                        myPlando[noPlando] = plando.new ( me.finallat, me.finallon, 9, 9, 9,
                        #  myPlando[noPlando] = plando.new ( me.finallat, me.finallon, me.mySoftAlt, goalalt, me.theHardAlt[i],
                                            WATERSPEED, me.myHeading, heading, me.myIndice,  tabCorrDirs[i], 999, 999);

                       
                        # ****** fin CREATE PLANDO *********
                       
                        # mise a jour de la couleur du plando en fonction de la profondeur d'eau
                  #      myPlando[noPlando].maj_my_color ( me.theSoftAlt[i] - me.theHardAlt[i] );  #  profondeur
                       
                       
                        me.myPtrs [i] = noPlando;


                }   # fin pas de plando EXISTANT dans cette direction

            }  # fin for 4 dirs


            me.traceOut();

            me.pas_fini = 0;  # c'est fini (bientot) on peut prendre les nouvelles primitives

            if (me.myIndice != ID_BARRAGE)  { # le barrage ne change pas d'altitude
           
                # mise a jour du modele : mise du modele a sa nouvelle altitude
                if (me.mySoftAlt > AltLacBarrage) me.mySoftAlt = AltLacBarrage; # ecretage
 
               me.updateHeight  (me.mySoftAlt);   # me.altN = alt courante, me.mySoftAlt = goal
 
            }
       
        },
       
        # ====== fin moteur de gestion du comportement des plandos
        # ====== fin MOTEUR : LA SUBSTANTIFIQUE MOELLE DU PROGRAMME
       

FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby FranzyG35 » Fri Dec 04, 2020 1:24 am

Thanks for pasting this at the end of trigger.xml

trigger.xml (part 3/3) :

Code: Select all
# ====== CONSTRUCTEUR de plando
       
        new : func (currLat, currLon, iniAlt, goalAlt, hardAlt, spd, heading, headMove, parentId, dir, x, y) {

       
            # iniAlt est mon altitude de larguage
            # goalAlt est l'altitude finale a atteindre apres deplacement
            # ecrasement des parametres pour test PHNL
            iniAlt = 11; goalAlt = 11; hardAlt = 9;
           
           
                var m = {
                        parents : [plando],

                        myPtrs : [-1,-1,-1,-1],
                           
                        theHardAlt: [-1,-1,-1,-1],    # altitude du sol dans les 4 directions

                        theSoftAlt : [-1,-1,-1,-1],   # niveau de l'eau dans les 4 directions
                        moving : 0,
                        movingH : 0,
                        pas_fini : 0,
                        x:x, y:y
                }; 
            me.petitCompteur = 0;   # raz compteur de traces

            # essai pour stocker une info dans l'arbre des props, dont celle ci qui fonctionne
            m.Barrage = 0;
           
            heading = headMove;    # c'est la merde alors j'ecrase le parametre heading avec le parametre headMove et voila
           
            m.kias = spd;
        #   m.heading = headMove;        # distinguer le heading du modele -heading- et la direction de son movement -headMove-
            m.heading = m.course = headMove;        # distinguer le heading du modele -heading- et la direction de son movement -headMove-
                                                    # apparemment ils sont melanges et on ne peut guere les distinguer A CREUSER
        #  m.interval = 10;
        #  m.length = 10;   # nm (longueur d'un leg ?)
            m.roll = 0;
   
            ###############

                                                                                #  pour la branche MODEL
            # Find the next index i available for "models/model[i]" and create property node
            #     directly attached to the root : /models/model[i]  !!!

            var n = props.globals.getNode ("models", 1);
            for (var i = 0; 1; i += 1) {
                if (n.getChild("model", i, 0) == nil)
                    break;
            }
            m.model = n.getChild ("model", i, 1);
                                                                                #  pour la branche AI
            # Find the next index for "ai/models/plando" and create property node in : /ai/models/model[i]
           
            var n = props.globals.getNode ("ai/models", 1);
            for (var i = NUMERO_INITIAL_DE_PLANDO ; 1; i += 1) {
                var cn = n.getChild ("ship", i, 0);
                # var cn = n.getChild ("wingman", i, 0);
                if (cn == nil) break;

                if (cn.getNode("id") == nil or cn.getNode("id").getValue() == nil)
                break;
            }
             m.ai = n.getChild ("ship", i, 1);
           # m.ai = n.getChild ("wingman", i, 1);    # plando on va plutot les appeler wingman pour qu'on voie leur indice dans la map
                                                    # on peut aussi recompiler flighgear pour accepter le nom plando en plus
                                                    # NON en fait on va remettre plando : wingman c'est seulement pour les tests
                                                    # l'affichage sur la carte est carrement bordelique et ne servira a rien en operationnel
                                                    # ACHTUNG : 3 endroits a modifier


            m. myIndice = i;       # sauver l'indice comme id de l'objet plando
   
            noPlando = i;
           
            m. myLat = currLat;     # sauver les coordonnees de lancement de l'objet plando
            m. myLon = currLon;     # NOUVEAU : le leg de deplacement ne fera que la largeur du plando
                                    # NOUVEAU : la fin du leg qui declenche le checkMyEnvironment
                                    #     NON ne rien foutre a la fin du leg
                                    # le leg ne sert qu'a mettre un peu de realisme dans le mouvement de l'eau
                                    # le vrai interet c'est de creer les plandos avec leurs chainages
            m. myHeading = heading;  # heading du modele
            m. myHeadMove = headMove; # cap de sa trajectoire
            m. mySpeed = spd;
           
            m.goalAlt =  goalAlt;    # stockage de l'altitude souhaitee a la creation (glissement en altitude lors du deplacement initial)
           
            m.deltaAlt = iniAlt - goalAlt;
           
            ###############  branche AI
            # creation des parametres du node ai de l'objet
       
            m.ai.getNode ("id", 1).       setIntValue (i);
           
            m.ai.getNode ("ship", 1).  setBoolValue(1);
      #      m.ai.getNode ("wingman", 1).  setBoolValue(1);
            m.ai.getNode ("valid",  1).   setBoolValue(1);
      #      m.ai.getNode ("texture-path",  1). setValue("Models/0Barrage/TexturesPlando/camo.png");
            m.ai.getNode ("texture-path",  1). setValue("TexturesPlando/camo.png");
      #      m.ai.getNode ("name",  1). setValue("plando"~i);    # c'est ce qui apparait sur la carte pour le type ship
             m.ai.getNode ("name",  1). setValue(""~i);
           
   
            var txtcallsign = "" ~ m. myIndice; #  ~ " alt=" ~ iniAlt ~ " vitesse="~spd;
            m.ai.getNode ("callsign", 1). setValue (txtcallsign);   # /ai/models/aircraft/callsign = "toto"


            m.latN = m.ai.getNode ("position/latitude-deg",  1);  # currLat;
            m.lonN = m.ai.getNode ("position/longitude-deg", 1);  # currLon;
            m.altN = m.ai.getNode ("position/altitude-ft",   1);  # iniAlt;
           
            m.hdgN   = m.ai.getNode ("orientation/true-heading-deg", 1);
            m.pitchN = m.ai.getNode ("orientation/pitch-deg", 1);
            m.rollN  = m.ai.getNode ("orientation/roll-deg", 1);

            # essai pour stocker cette info dans l'arbre des props
            m.Barrage = m.ai.getNode ("Barrage",  1);
            m.Barrage.setBoolValue(0);

            # position de depart ai
           
            # d'apres AIM9 fox2.nas : "Compute initial position"
            # following Vivian's code in AIModel/submodel.cxx
            #             ici : pas besoin de computer recuperer les coordonnees recues en parametre
           
            m.latN.setDoubleValue (currLat);
            m.lonN.setDoubleValue (currLon);
            m.altN.setDoubleValue (iniAlt);
           
            m.hdgN.setDoubleValue (heading);
            m.pitchN.setDoubleValue (0);
            m.rollN.setDoubleValue  (0);

        #-------

        m.myHardAlt = hardAlt;      # altitude du sol en cet emplacement
        m.mySoftAlt = goalAlt;      # altitude de la surface de l'eau a cet emplacement à l'instant present

        m.myBarrageMem = 0;   # les plando ne sont pas a priori dans le barrage
       
        # special pour le barrage
        if (m. myIndice == ID_BARRAGE ) {
       
            #   me.creerBarrage ();   # initialisation specifique si le plando est le premier et appartient donc au barrage (a la chute d'eau)
       
                m.myBarrageMem = 1;      # ce plando est dans le barrage
           
                me.Barrage = m.ai.getNode ("Barrage",  1);
                me.Barrage. setBoolValue(1);  # true
               
                # recalculer la cote du lac de barrage : d'apres la valeur reelle lue par getHardAlt (on l'avait mise au pif pour demarrer)
                m.myHardAlt = me.getHardAlt (m.myLat, m.myLon, m.myHeading + headAngle[K_AMONT]);

               
                # les altitudes sont OK - c'est bien hardamont qu'il faut utiliser ici pour l'altitude du Lac
                var myHardamont  = me.getHardAlt (m.myLat, m.myLon, m.myHeading + headAngle[K_AMONT]);
                var myHardaval   = me.getHardAlt (m.myLat, m.myLon, m.myHeading + headAngle[K_AVAL]);
                var myHarddroite = me.getHardAlt (m.myLat, m.myLon, m.myHeading + headAngle[K_RIGHT]);
                var myHardgauche = me.getHardAlt (m.myLat, m.myLon, m.myHeading + headAngle[K_LEFT]);
               
                m.theHardAlt[K_AMONT] = myHardamont;
                m.theHardAlt[K_AVAL]  = myHardaval;
                m.theHardAlt[K_RIGHT] = myHarddroite;
                m.theHardAlt[K_LEFT]  = myHardgauche;

                m.finallat = m.myLat;
                m.finallon = m.myLon;
               
                m.mySoftAlt = m.myHardAlt;  # 1619.5 ft + 20 non j'ai pas envie : le lac : ses alts hard et soft seront egales . point
                m.altN.setDoubleValue (m.mySoftAlt);
                m.ai.getNode  ("position/reste-a-faire", 1) .setDoubleValue (0);
               
                var msg = "Altitude cote du Lac de barrage "~ m.myHardAlt~" ";  # 1619.5 ft
                               
                var textinfo = "BARRAGE : niveau"  ~ " hard =" ~ int (m.myHardAlt) ~ " soft="~int (m.mySoftAlt);
                # me.tracer_m (textinfo);
                me.petitCompteur += 1;
                m.ai.getNode ("information00"~me.petitCompteur, 1). setValue (textinfo);
               
                m.myPtrs[K_AMONT] = -1;
                m.myPtrs[K_AVAL]  = -1;
                m.myPtrs[K_LEFT]  = -1;
                m.myPtrs[K_RIGHT] = -1;
       
            }
            else {  # pour tous les plandos sauf pour le barrage
           
                 m.mySoftAlt = goalAlt;      # altitude de la surface de l'eau a cet emplacement à l'instant present
                #  m.mySoftAlt = iniAlt;
                  m. alt_now = iniAlt;       # altitude au larguage sert au decrement de l'altitude lors du deplacement du modele
                 
                # ACHTUNG dir peut ne pas etre initialise ici
               
                m.myPtrs[dir] = parentId;   # sauvegarde du pointeur sur le pere
               
                # calcul de l'emplacement final de ce plando apres son deplacement de la largeur
               
                m.reste = m.ai.getNode  ("position/reste-a-faire", 1);
                m.reste.setDoubleValue (LARGEUR_MODELE);

                # ---
                # cette propriete m.coord est bien utile (librairie geo) car elle permet de faire des calculs tres necessaires
                # comme apply_course_distance() ou alt() voir ci-dessus

                var dist = LARGEUR_MODELE+2;     # en metres : c'est la largeur du modele

                m.coord  = geo.Coord.new ();
               
                # Donc 2 attributs de l'objet tres utiles :
                m.coord. set_latlon (currLat, currLon, iniAlt);    # emplacement de larguage (place du pere) (voila comment faire l'init)
               
                # il semble que ce qui suit ecrase/modifie m.coord
               
                m.goal  = geo.Coord.new ();
                m.goal.set_latlon (currLat, currLon, iniAlt);
                m.goal.apply_course_distance (headMove, dist);  # Mandatory absolute bearing (0?360)
                                                                # Mandatory distance in metres
                m.finallat = m.goal.lat();
                m.finallon = m.goal.lon();
               
                m. update();      # positionnement de l'objet dans l'espace d'apres ce qu'on vient d'initialiser
        }

           
            ###############   branche MODEL
            # creation de la branche /models/model[i] de l'arbre
       
            m.model.getNode ("path", 1). setValue (modelVariable);            # parametre du new "Models/..... .xml"
           
            # la branche ne contient qu'uniquement des pointeurs sur les valeurs de la branche AI qui est seule modifiee en temps reel
            # sauf peut-etre si ces valeurs sont statiques / constantes

            m.model.getNode ("latitude-deg-prop", 1).  setValue (m.latN.getPath());    # chemins vers les donnees de localisations
            m.model.getNode ("longitude-deg-prop", 1). setValue (m.lonN.getPath());    # de l'ai
            m.model.getNode ("elevation-ft-prop", 1).  setValue (m.altN.getPath());
           
            m.model.getNode ("heading-deg-prop", 1).   setValue (m.hdgN.getPath());
            m.model.getNode ("pitch-deg-prop", 1).     setValue (m.pitchN.getPath());
            m.model.getNode ("roll-deg-prop", 1).      setValue (m.rollN.getPath());
               
        m.model.getNode ("load", 1). remove();  # indicateur creation/chargement du modele en cours -> absent/viré = completed

        # notify any listeners that a new model has been added
        setprop ("/ai/models/model-added", m.ai.getPath());
       
       var canvasEnabled  = 1;
 if (canvasEnabled == 1) {
        ###############   branche CANVAS
        # creation de la branche /canvas/by-index/texture[i] de l'arbre
           
                # ******************* add a canvas and stick it to the object
               
                var (width, height) = ( 64,64 );
                # Create a standalone Canvas (not attached to any GUI dialog/aircraft etc)
                m.myCanvas = canvas.new ({
                    "name": "p"~m. myIndice,   # The name is optional but allows for easier identification
                    "size": [width, height], # Size of the underlying texture (should be a power of 2, required) [Resolution]
                    "view": [width, height],  # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]
                                            # which will be stretched the size of the texture, required)
                    "mipmapping": 1       # Enable mipmapping (optional)
                });

                # creating the top-level/root group which will contain all other elements/group
                canvasRoot = m.myCanvas.createGroup();
                               
                m.myImage = canvasRoot.createChild("image")
                                    .setFile("AI/Aircraft/plando/TexturesPlando/red2.png")
                                    .setSize(64,64)
                                    .setTranslation(0,0);

                m.colorCpt = m.myIndice;
                                   
                m.myText = canvasRoot.createChild("text")
                                .setText(""~int(m.mySoftAlt))
                                .setFontSize(16, 0.9)          # font size (in texels) and font aspect ratio
                                .setColor(0,0,1,1)             # blue, fully opaque
                                .setAlignment("center-center") # how the text is aligned to where you place it
                                .setTranslation(30, 30);       # where to place the text                   
                                   
                #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                # Add a placement by replacing the textured face "mySurface" in the 3D model
                # This replaces the texture on the aircraft and attaches the Canvas texture
                gui.popup("addPlacement has been called :)");
                m.myCanvas.addPlacement ({ "node" : "mySurface" });
                #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
               
                # debug : Create a Canvas dialog window to hold the canvas and show that it's working
                # the Canvas is now standalone, i.e. continues to live once the dialog is closed!
                #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                # How can I position the dialog on screen- They all pile up in the corner !!!
                 var window = canvas.Window.new([100,100],"dialog");
                 window.setCanvas (m.myCanvas);
   
                # ******************* fin add a canvas stuck on the object
   } #end if (canvasEnabled == 1)             
               

                                     
        return m;   # retourne l'objet m plein de proprietes contenu dans cette classe - et return me; ca serait possible ? 
        },
        # ====== fin CONSTRUCTEUR de plando
 
        # ====== 
        updateHeight: func (goal_Alt) {  # mise a jour reguliere de l'objet a chaque tic horloge t : repositionnement de l'objet dans l'espace
       
                # return;  # shunt  SAUTILLEMENT DES PLANDOS A CORRIGER - OK             
         
                me.movingH = 1;  # le update met le plando en mouvement - on refusera les modifs d'altitude pendant son deplacement
                                                       
                var simTimeDeltaSec   = props.globals.getNode("sim/time/delta-sec",1);                                         
                var dt = simTimeDeltaSec.getValue();  # LE DELTA T depuis le dernier appel me.update()
               
                var alt_ft = me.altN.getValue();   # altitude actuelle

                # distance verticale parcourue pendant l'intervalle de temps dt
                var XdeltaAlt = WATERVSPEED * dt * FT2M;
               
                # XdeltaAlt = 1;    # essai 1 metre parcouru
               
                # ca serait bien de mettre un pitch au plando : a faire plus tard
                var pitch_deg = 0;
               
                #-----
                # calcul de combien le modele s'est avance sur sa trajectoire prevue (montee du niveau)
                # me.tracer ( " ****** UPDATE : now "~ alt_ft ~ " VSPEED : "~ WATERVSPEED~ " delta : "~ XdeltaAlt ~ " goal : "~ int (goal_Alt), 3);
               
                var newalt = 0;     # nouvelle altitude courante apres le delta t ecoule
                if (alt_ft > goal_Alt) newalt = alt_ft - XdeltaAlt;
                else                   newalt = alt_ft + XdeltaAlt;
                                                                     
                me.tracer ( "UPDATE_HGT : now : "~alt_ft~" goal : " ~ goal_Alt~" newalt "~newalt~ " AltLacBarrage "~ AltLacBarrage~ "", 3);
               
                #-----
                # POSITIONNEMENT DANS L'ESPACE par modification de altN ( puis a terme  pitch/roll)
               
                # maj dans l'arbre des props : ca fait bouger le modele
                me.altN.setDoubleValue (newalt);   #  repositionnement du modele a sa bonne altitude a t

                me.myText.setText (""~int(newalt)); # modif de l'altitude dans le texte de mon canvas
                               
                if (math.abs (newalt - goal_Alt) < XdeltaAlt)  {     # si la distance restant a parcourir desormais est inferieure a
                                                                    # celle qu'on parcourt en un tic : on est arrive a la position finale (alt)
                        me.movingH = 0;
               
                        return;
                }

             settimer (func me.updateHeight (goal_Alt), 0);
               
        },
 
        # ====== update : deplacement du modele de plando dans l'espace
        #                 ATTENTION : ce programme est appele toutes les 10 ms voire plus !!!
       
        update: func {      # mise a jour reguliere de l'objet a chaque tic horloge : repositionnement de l'objet dans l'espace
                            # me <=> this
           
            me.moving = 1; # le update met le plando en mouvement - on refusera les modifs d'altitude pendant son deplacement
           
                                                   
            var simTimeDeltaSec   = props.globals.getNode("sim/time/delta-sec",1);
            var dt = simTimeDeltaSec.getValue();  # LE DELTA T depuis le dernier appel me.update()
           
            # var textinfo = "UPDATE ========== : "  ~ " DELTA T :" ~ dt ;
            # me.tracer (textinfo, 3);

            # var alt_ft = me.coord.alt();
            #  var alt_ft = me. alt_now;
             var alt_ft = me.altN.getValue();   # altitude actuelle
             
            # la mise a jour ne s'effectue que pour les objets declares dans l'arbre des proprietes AI
            # donc : les autres sont immobiles - ce sont ces proprietes la qui sont utilisees dans les animations des modeles ?
            # par le moteur ?
           
            #-----
            # calcul de combien le modele s'est avance sur sa trajectoire prevue (largeur du modele LARGEUR_MODELE)
            # vitesse (constante aquatique 36kts ?), heading (perpendiculaire au barrage 120 ?)
            # pour pouvoir l'arreter quand il aura parcouru son chemin
            #-----
            # Get horizontal distance and set position and orientation
            # calculer x = vt  ( distance horizontale parcourue pendant l'intervalle de temps dt )
           
            var dist_hor_m = WATERSPEED * dt * FT2M;   # WATERSPEED : vitesse par defaut de la flotte
           
            # dist_hor_m = 7;    # essai 7 metres parcourus

            # distance verticale parcourue pendant l'intervalle de temps dt
            #    (inclut le calcul de la vitesse verticale) :
            # on sait que le modele se sera deplace de deltaAlt a la fin du deplacement de LARGEUR_MODELE
            var dAlt = WATERSPEED * dt * FT2M * me. deltaAlt / LARGEUR_MODELE ;
           
           
            #  >>>>>>>>>>>>>>>>> PROBLEME dAlt N'EST PAS correct  <<<<<<<<<<<<<<<<<<<<<
           
             dAlt = 0.1;    # essai 1 metre parcouru
           
            # dAlt /= 100;     # essai de diviser la vitesse de descente par 100 (mySoftAlt est ecrasee apparemment)
            # ca annule bien le taux de descente
           
            var altnew = 0;
            if (alt_ft > me.goalAlt) altnew = alt_ft - dAlt;
            else                     altnew = alt_ft + dAlt;
           
            me. alt_now = altnew;
           
            var pitch_deg = 0;
            var # hdg_deg = int (me.hdgN);  # nil !!!!
                # hdg_deg = me.ai.getNode ("heading_deg", 1). getValue() or 5 ;
                hdg_deg = me. myHeading;

           
            #-----
            # calcul des nouvelles coordonnees atteintes en parcourant dist_hor_m sur le cap hdg_deg
            # les coordonnees au point precedent on ete stockee au precedent tic
         
            me.coord.apply_course_distance (hdg_deg, dist_hor_m);
           
            #-----
            # POSITIONNEMENT DANS L'ESPACE par modification de latN, lonN et altN + heading et pitch/roll
           
            # maj dans l'arbre des props
            me.latN.setDoubleValue (me.coord.lat());
            me.lonN.setDoubleValue (me.coord.lon());
            me.altN.setDoubleValue (altnew);   # c'est la qu'on repositionne le modele a sa bonne altitude
           
            # me.pitchN.setDoubleValue (pitch_deg);   # modifier le pitch : a faire plus tard
            # me.hdgN.    setDoubleValue (hdg_deg);   # le heading du model reste constant pendant son deplacement
           

            #-----
            # reste a parcourir
            me.course = me.coord.course_to (me.goal);          # cap et distance restant a parcourir desormais
            me.leg_remaining = me.coord.distance_to (me.goal);
           
            me.reste.setDoubleValue (me.leg_remaining);     # stockage dans l'arbre inutile sauf pour trace
           
            if ((me.leg_remaining -= dist_hor_m) < 0) {   # si la distance restant a parcourir desormais est inferieure a
                          # celle qu'on parcourt en un tic, alors on est arrive a la position finale (lat, lon)
           

                    # maj de la vitesse du plando : arreter le plan d'eau
                    me.ai.getNode  ("velocities/true-airspeed-kt", 1). setValue(0);
                   
                    me.moving = 0;
                   

                   
                    # mise a jour de ma couleur en fonction de la profondeur d'eau
            #        me.maj_my_color ( me.mySoftAlt - me.myHardAlt );
                   
                    # le plando a fini de se deplacer de la largeur du modele (on est eventuellement loin de la cascade avec plein de modeles entre nous)
                    # on est donc un front avec une certaine altitude et epaisseur d'eau et on doit eventuellement s'etendre vers l'aval
                    # c'est quand meme dans la nature d'un m3 d'eau de se repandre dans le sens de la declivite (en eventail)
                   
                    me.checkMyEnvironment (me. myIndice, me.mySoftAlt, me.myHardAlt, END_OF_TRIP);
                   
                    return;
            }

            # ==
            # nouvelles coordonnees de l'objet apres delta t
           
            # rearmement timer delta t   0 !!!!!!!!! reexecution immediate
            # donc le delta t est gere ailleurs : simTimeElapsedSec ? mais ou ?????
            # peut-etre qu'on se contente de boucler immediatement - ca fait quelque millisecondes ?!
           
            settimer (func me.update(), 0);
        },
       
    };   # fin de mon hash plando
    #======================

            #======================
            # fonction de larguage d'un plan d'eau : DU PREMIER PLANDO SEULEMENT


            var larguer_plando = func () {


                var softAlt  = SoftAlt;
                var currLat  = CurrLat
                var currLon  = CurrLon;
                var currHead = HDG_START;

                noPlando = 1;
                myPlando[noPlando] = plando.new ( currLat, currLon, 9, 9,
                                    9, 0, currHead, currHead, -1, 2, 0, 0);
                                                                # speed 0 kts pour le 1er plan d'eau sur le barrage
                                                                # -1 id du pere, 2 : direction (indice dans myPtrs[])  0,0 = x,y

                noPlando += 1;
               
                var nextPD = myPlando[1];
                nextPD.checkMyEnvironment (1, 9, 9, END_OF_TRIP);
                }
               
            # fin larguage d'un plan d'eau
            #======================
   
   
            #=============================================
            # modif texture d'un canvas
           
            var canvasChange = func () {

                # gui.popupTip ("Change !");
               
                for (var iii = 1 ; iii < 6 ;  iii+=1 ) {
                    var alt = myPlando[iii]. mySoftAlt;
                   
                    if (myPlando[iii]. movingH == 0) { # l'objet a fini de se deplacer on lui assigne une nouvelle consigne
                   
                        gui.popupTip ("Change ! " ~ myPlando[iii]. mySoftAlt);
                       
                            if (alt >= 19) alt = 11;
                        # else if (alt <= 12) alt = 20;
                        else     alt = 20;
                        # else break;
                   
                        myPlando[iii]. mySoftAlt = alt;   # mySoftAlt est le goal
                       
                        gui.popupTip ("updateHeight ! " ~ alt);
                       
                        myPlando[iii].updateHeight (alt); # goal
                    }
                   
                    myPlando[iii].colorCpt += 1;
                   
                    if (myPlando[iii].colorCpt > 4) myPlando[iii].colorCpt = 0;
                       
                #  gui.popupTip ("updateColor !  "~ iii~ " "  ~myPlando[iii].colorCpt);
                   
                    myPlando[iii].maj_my_color (myPlando[iii].colorCpt);
                }   
           
                settimer (func {   canvasChange ();  }, 3);    # rearmement du sablier         
            }
   

            noPlando = NUMERO_INITIAL_DE_PLANDO;
               
           
            # larguer tout de suite le plando 1
            larguer_plando ();
           
            settimer (func {canvasChange ();  }, 10);
   
            #=============================================

            # clic pris en compte
            sortir = 1;

        }  # fin if (getprop ("sim/model/startTheShow") == 1) {

        if (getprop ("sim/model/startTheShow") == 2) {

            # rien a faire : clic superfétatoire
            sortir = 1;
        }

        # sortir = 1 : mettre le timer a 0 sinon rearmer le timer pour une seconde pour boucler en attente du clic declencheur
        if (sortir == 0) { settimer (func { loop (id) }, 1); }
        else { settimer (func { loop (-1) }, 1); }  # id a la place de -1 laisse la boucle s'executer toutes les secondes

    } # fin de la loop d'attente du clic sur le trigger

    # armer le timer pour 500ms et declencher alors le traitement loop
    settimer (func { loop (loopid) }, 0.5);


    ]]></load>
    <unload><![CDATA[
        var loopid = 0;
            print ("bye from trigger.xml");
            print ("");
        loopid += 1;
      ]]></unload>
  </nasal>

</PropertyList>

FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby wkitty42 » Fri Dec 04, 2020 1:51 pm

FranzyG35 wrote in Fri Dec 04, 2020 1:22 am:I'll need a 3rd post as this code is still too big) :oops:

you can always use a paste site like pastebin and post a link the the paste here ;)
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."
User avatar
wkitty42
 
Posts: 9148
Joined: Fri Feb 20, 2015 4:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 20.04

Re: Changing model textures

Postby gordonshamway23 » Fri Dec 04, 2020 9:17 pm

Ok, I followed your steps, copied all the code into trigger.xml and I am able to see your red square on the runway.
If I open the the nasal console, (Main menu -> Debug -> Nasal console), in the moment when your model is loaded
I get a nasal parse error in Models/FUN/plaque.ac line 1090. I quess that means line 1090 in the trigger.xml.
Are you also getting this error? Until this error is fixed, the canvas can't work.

PS: Could it be, that there are two } missing after "gui.popupTip (" Started !");" ?
gordonshamway23
 
Posts: 24
Joined: Sun Nov 22, 2020 8:15 pm

Re: Changing model textures

Postby Hooray » Fri Dec 04, 2020 9:38 pm

Speaking in general, it would have been a good idea to share a self-contained example that people can easily recreate/follow via the Nasal console.
Apart from that, it's generally also a good idea to use io.load_nasal() for such Nasal "blobs" - that way, you also end up with support for RAD, i.e. rapid-prototying, because whenever the XML file/bindings are loaded (executed), the corresponding Nasal module will be reloaded from disk.

Note that this will also fix up the offsets shown for parse errors, such files don't need to use the nas extension.

In that context, it makes sense to use Nasal's API library to catch errors easily. Using these in conjunction would even make it possible to implement a trigger based reload mechanism (think listeners). Note that jsb has created a dedicated Nasal module exactly for that.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Changing model textures

Postby FranzyG35 » Sat Dec 05, 2020 5:15 am

Hello

Thank you for your interest in my development issue.

With this zip file it should be easier (it's my 1st try with google drive) :
https://drive.google.com/file/d/19J323wDXNZGSX2OfAosIXILlcmFcjv-B/view?usp=sharing

Then the procedure is as follows:

Assuming you have the PHNL scenery installed :
1- Add this line to the w160n20/w158n21/367568.stg
OBJECT_STATIC Models/FUN/trigger.xml -157.927 21.3141 4 45
2- in FGDATA/Models/ copy the FUN directory attached
3- Start flightgear in PHNL RWY O4R with any aircraft
change the view with "V" and a couple of ctrl-Xes
4- You'll see a red square on the RWY : click on it
5- Now you have 10 seconds to move the 5 dialogs anywhere you want (as they pileup in the left corner)

You'll see the changes of texture and text in the dialogs as the models appear and move


Now the issue I've been trying to solve is that the textures and text of the models
do not change accordingly as they should.
Look for the $$$$$$$$ string in trigger2.xml to locate the instruction below
m.myCanvas.addPlacement ({ "node" : "mySurface" });
mySurface corresponds to the face description in the ac model from plaque.ac :
name "mySurface"

Nota :

Nasal parse errors : I noticed the parse errors lines in nasal are not advertised properly.
- the location is not the .ac file but the .xml file that include the .ac as <path>
- the offset of the <nasal> declaration (here 32) must be added to have the right figure...

Thank you Hooray for the workaround with io.load_nasal().

Let me know if you need additional info

Thanks again for your involvement

Franck
FranzyG35
 
Posts: 15
Joined: Wed Nov 16, 2016 11:09 pm

Re: Changing model textures

Postby gordonshamway23 » Sat Dec 05, 2020 4:00 pm

Hello everyone!

Good news, I was able got your canvas on a scenery object working. I had to reduce your code to a minimal example
because I don't understand what you are intending with all that code. And your structure and indentation is a little messy for my taste.

In your files on google drive the plague.ac is erronous, instead of "mySurface" the object name is "Plaq" or so. I corrected that.

Here the plaque.ac file:

Code: Select all
AC3Db
MATERIAL "bleu" rgb 0.000 0.000 1.000  amb 0.800 0.800 0.800  emis 0.000 0.000 0.000  spec 0.200 0.200 0.200  shi 64 trans 0.000
OBJECT world
name "Blender_exporter_v3.0__plan.ac"
kids 2
OBJECT poly
name "mySurface"
data 5
Plane
texture "TexturesPlando/red.png"
texrep 1 1
crease 40.0
numvert 4
-2.66423 0 2.35963
2.66423 0 2.35963
-2.66423 0 -2.35963
2.66423 0 -2.35963
numsurf 1
SURF 0X0
mat 0
refs 4
0 0 0
1 1 0
3 1 1
2 0 1
kids 0


And here your trigger.xml reduced to a minimum, so one can understand your problem and test the solution real quick.

Code: Select all
<?xml version="1.0" encoding="iso-8859-1"?>

<PropertyList>
   
    <path>plaque.ac</path>

    <animation>
        <type>pick</type>
        <object-name>mySurface</object-name>
        <visible>true</visible>

        <action>
            <button>0</button>
            <repeatable>false</repeatable>

            <binding>
                <command>property-assign</command>
                <property>sim/model/startTheShow</property>
                <value>1</value>
            </binding>

        </action>
    </animation>
   
 
  <nasal>
    <load><![CDATA[

                var (width, height) = ( 256,256 );
                var mySurfCanvas = canvas.new ({
                    "name": "mySurfaceCanvas",   
                    "size": [width, height],
                    "view": [width, height], 
                    "mipmapping": 1     
                });

                var mySurfCanvasRoot = mySurfCanvas.createGroup();
                               
                mySurfCanvasRoot.createChild("image")
                                    .setFile("Models/FUN/TexturesPlando/red2.png") # I had to correct the path here
                                    .setSize(256,256)
                                    .setTranslation(0,0);
                                   
                mySurfCanvasRoot.createChild("text")
                                .setText("Hello world")
                                .setFontSize(16, 0.9)         
                                .setColor(0,0,1,1)             
                                .setAlignment("center-center")
                                .setTranslation(30, 30);                   
                                   

                mySurfCanvas.addPlacement ({
                  "type" : "scenery-object",
                  "module-id" : _module_id,
                  "node" : "mySurface"
                });


                var window = canvas.Window.new([100,100],"dialog");
                window.setCanvas (mySurfCanvas);

    ]]></load>
    <unload><![CDATA[

      ]]></unload>
  </nasal>

</PropertyList>



I did not find any documentation on that. I had to read c++ source code for that.
In the addPlacement hash parameter, you need to set the key "type" to "scenery-object". In addition flightgear requires a "module-id" key in that hash
which indentifies your loaded scenery model. Thankfully that id is exposed in the global namespace of the <load> section and is accessable via "_module_id".

Have a nice weekend.
gordonshamway23
 
Posts: 24
Joined: Sun Nov 22, 2020 8:15 pm

Next

Return to Nasal

Who is online

Users browsing this forum: No registered users and 2 guests