• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FSX I can't link switch with indicator and backlighting

Messages
23
Country
poland
Hi!

I work on project of FSX's conversion of an excellent An-28 made by DPL for X-plane. Some of the switches and indicators have already been coded. I would like to link some of the switches with some of the indicators so that switching a switch on would produce switching an indicator ON, as well as switching the backlighting on. However I can not link all that three elements toghether. Example of such linked switch, indicator and backlighting below. I guess that the solution is trivial but I can not go through it so far... I need a modeldef.xml format of code for FSX.

Besides this I would like to say "thank you" for all of you, especially n4gix and a few others of the developers who share their knowledge and teaching us this kind of the 3D art. Without you I could not step further as I did. Thanks!


INDICATOR:


<PartInfo>
<Name>AN28_Vibration_needle_left</Name>
<AnimLength>100</AnimLength>
<Animation>
<Parameter>
<Code>
(A:TURB ENG VIBRATION:2, percent) 10 /
</Code>
</Parameter>
</Animation>
<MouseRect>
<TooltipText>Vibration (%((A:TURB ENG VIBRATION:2, percent))%!3d! %)</TooltipText>
<Cursor>Hand</Cursor>
</MouseRect>
</PartInfo>


SWITCH:


<PartInfo>
<Name>AN28_VibrInd_SW</Name>
<AnimLength>2</AnimLength>
<Animation>
<Parameter>
<Code>
(L:VibrInd_SW, enum)
</Code>
<Lag>400</Lag>
</Parameter>
<Animation>
<MouseRect>
<Cursor>Hand</Cursor>
<TooltipText>Left Fuel Indicator Switch</TooltipText>
<MouseFlags>LeftSingle+RightSingle+Wheel</MouseFlags>
<CallbackCode>
(M:Event) 'RightSingle' scmp 0 == if{ (L:VibrInd_SW, enum) -- 0 max (>L:VibrInd_SW, enum) }
(M:Event) 'LeftSingle' scmp 0 == if{ (L:VibrInd_SW, enum) ++ 1 min (>L:VibrInd_SW, enum) }
(M:Event) 'WheelUp' scmp 0 == if{ (L:VibrInd_SW, enum) ++ 0 max (>L:VibrInd_SW, enum) }
(M:Event) 'WheelDown' scmp 0 == if{ (L:VibrInd_SW, enum) -- 1 min (>L:VibrInd_SW, enum) }
</CallbackCode>
</MouseRect>
</PartInfo>


INDICATOR BACKLIGHTING:


<PartInfo>
<Name>AN28_VibrInd_BL</Name>
<Visibility>
<Parameter>
<Code>
(L:VibrInd_SW, enum) 0 &gt;
(A:LIGHT CABIN, bool) 0 &gt;
and
(A:CIRCUIT GENERAL PANEL ON, bool) 0 &gt;
and
if{ 1 } els{ 0 }
</Code>
</Parameter>
</Visibility>
</PartInfo>


Best Regards
IntruderPL
 
Last edited:
Messages
1,749
Country
unitedstates
I don't have time to check your code. but here is a tip!

Use visibility tags for showing the back lighting and then you only need to link up 2 codes.

DG:)
 
Messages
23
Country
poland
Well, good idea! Thanks DG :) I will move the visibility part of backlighting to the code of the switch.
Now, I only need to get the indicator's needle move only when the switch is on.
I will appreciate any help/suggestions.
 

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
INDICATOR:
All you need to do is add the condition to your needle's script to have the needle move only if the switch is active (set), and provide a keyframe number for the "parked (static) position" when the switch is off:

Code:
<PartInfo>
	<Name>AN28_Vibration_needle_left</Name>
	<AnimLength>100</AnimLength>
	<Animation>
		<Parameter>
			<Code>
			     (L:VibrInd_SW, enum) 1 ==
                              if{ (A:TURB ENG VIBRATION:2, percent) 10 / }
                              els{ 0 }
			</Code>
		</Parameter>
	</Animation>
	<MouseRect>
		<TooltipText>Vibration %((A:TURB ENG VIBRATION:2, percent))%!3d!</TooltipText>
		<Cursor>Hand</Cursor>
	</MouseRect>
</PartInfo>

BTW, I fixed the syntax on your <TooltipText> as well.
 
Messages
23
Country
poland
So I assume that this line:

els{ 0 }

is that keyframe for needle's parked position and I am not about to do something more in needle 3D model's animation. Is that correct?

I will give it a try to see if I can use the model above.
Also I want to explain that I used many of your codes and explanations from here (the forum) to bring the life into the project of An-28. Thank you very much Bill! :)

EDIT:

I had to add a <Lag>200</Lag> tag just below CODE tag and it works perfectly! Again, THANKS A LOT Bill and DG!
 
Last edited:

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
EDIT:

I had to add a <Lag>200</Lag> tag just below CODE tag and it works perfectly! Again, THANKS A LOT Bill and DG!

Great! Yes, the els{ 0 } will "park" the needle at the zero keyframe. If the "parked position" is mid-scale (such as an ammeter that has -/+ amps, then the keyframe would need to be 50... ;)

The <Lag> value determines how fast the needle (or other part) moves with respect to the sim variable. A value of 200 means "200 frames per second" so it's pretty quick. Some needles require more damping, so for those I lower the <Lag> value to 30 or thereabouts.
 
Messages
23
Country
poland
The <Lag> value determines how fast the needle (or other part) moves with respect to the sim variable. A value of 200 means "200 frames per second" so it's pretty quick. Some needles require more damping, so for those I lower the <Lag> value to 30 or thereabouts.

Nice tip! Thanks Bill :)

I will post here another issue to avoid unnecessary posting.

I've got an 3-pos switch of 3D landing/taxi lights. Both the lights are off in neutral position of the switch. Landing lights ON should be in switch'es UP position (inc/dec by left click) and Taxi light in its DOWN position (dec/inc by right click). Unfortunately the switch doesn't work as intended for unknown reason. The code I use so far works but not strictly as I've described above. Keyframing is like: 0 (up/landing on) - 50 (middle/lights off) - 100 (down/taxi on). I can invert keyframing if needed.

Code:
	<PartInfo>
		<Name>AN28_switch_3Dlight</Name>
		<AnimLength>100</AnimLength>
		<Animation>
			<Parameter>
				<Code>50 (L:3DLight_Switch,enum) 50 * +</Code>
				<Lag>400</Lag>
			</Parameter>
		</Animation>
		<MouseRect>
			<Cursor>Hand</Cursor>
			<TooltipText>Landing / Taxi Light Switch</TooltipText>
			<MouseFlags>LeftSingle+RightSingle+LeftRelease+RightRelease</MouseFlags>
			<CallbackCode>
				(M:Event) 'LeftSingle' scmp 0 ==
				if{
				-1 (>L:3DLight_Switch, enum)
				(>K:LANDING_LIGHTS_TOGGLE)
				}
				(M:Event) 'RightSingle' scmp 0 ==
				if{
				1 (>L:3DLight_Switch, enum)
				(>K:TOGGLE_TAXI_LIGHTS)
				}
				(M:Event) 'LeftRelease' scmp 0 ==
				if{ 0 (>L:3DLight_Switch, enum) }
				(M:Event) 'RightRelease' scmp 0 ==
				if{ 0 (>L:3DLight_Switch, enum) }
				(L:VC_Click,bool) ! (>L:VC_Click,bool)
				1 (>L:XMLClick,enum)
			</CallbackCode>
		</MouseRect>
	</PartInfo>

Radek Koterbski
vel IntruderPL
 
Last edited:

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
Okay, rather than deal with what's wrong with the mouse script above, other than mention that there is no way to turn OFF either landing or taxi lights...

I will instead post some "universal" script that I copy/paste/edit as required for all three position, center off switches. I've already edited it to use your L:variable:

Code:
<MouseFlags>LeftSingle+RightSingle+WheelUp+WheelDown</MouseFlags>
<CallbackCode>
  (M:Event) 'LeftSingle' scmp 0 ==
      if{ (L:3DLight_Switch, enum) -- -1 max (>L:3DLight_Switch, enum) }
  (M:Event) 'WheelDown' scmp 0 ==
      if{ (L:3DLight_Switch, enum) -- -1 max (>L:3DLight_Switch, enum) }
  (M:Event) 'RightSingle' scmp 0 ==
      if{ (L:3DLight_Switch, enum) ++ 1 min (>L:3DLight_Switch, enum) }
  (M:Event) 'WheelUp' scmp 0 ==
      if{ (L:3DLight_Switch, enum) ++ 1 min (>L:3DLight_Switch, enum) }
</CallbackCode>

This script will allow the user to use either the left/right mouse buttons, or the center wheel to roll the switch up/down.

Now, note that I've not specified any "action" in the above script to be taken when the switch is clicked or wheeled...

This is because I prefer to keep the script as "universal" as possible! I can easily add the "control logic" to either the <CallbackCode> itself, or in a separate <Update> logic section. I will show the first option in the example below.

In either case, note that all "toggle" type events are just that; click once ON, click again OFF. Not terribly easy to control! :mad:

So, the "safe" way to use them is to first check to see if they need to be changed. We do this by checking the state of the light circut, then sending the command event only if required.

Code:
<MouseFlags>LeftSingle+RightSingle+WheelUp+WheelDown</MouseFlags>
<CallbackCode>
  (M:Event) 'LeftSingle' scmp 0 ==
      if{ (L:3DLight_Switch, enum) -- -1 max (>L:3DLight_Switch, enum) }
  (M:Event) 'WheelDown' scmp 0 ==
      if{ (L:3DLight_Switch, enum) -- -1 max (>L:3DLight_Switch, enum) }
  (M:Event) 'RightSingle' scmp 0 ==
      if{ (L:3DLight_Switch, enum) ++ 1 min (>L:3DLight_Switch, enum) }
  (M:Event) 'WheelUp' scmp 0 ==
      if{ (L:3DLight_Switch, enum) ++ 1 min (>L:3DLight_Switch, enum) }

  (L:3DLight_Switch, enum) -1 == (A:LIGHT LANDING,bool) 0 == and if{ (>K:LANDING_LIGHTS_TOGGLE) }
  (L:3DLight_Switch, enum)  0 == (A:LIGHT LANDING,bool) 1 == and if{ (>K:LANDING_LIGHTS_TOGGLE) }
  (L:3DLight_Switch, enum)  0 == (A:LIGHT TAXI,bool)    1 == and if{ (>K:TOGGLE_TAXI_LIGHTS) }
  (L:3DLight_Switch, enum)  1 == (A:LIGHT TAXI,bool)    0 == and if{ (>K:TOGGLE_TAXI_LIGHTS) }
</CallbackCode>

Note that for each possible state of the (L:var), I'm first checking the state of the light circuit, then sending the command event.

I hope this is understandable, and will help you in the future as well! :teacher:
 
Messages
23
Country
poland
Oushhhhhhh! :eek:
Are you a teacher in RL Bill? :) You explained me the whole thing in fully understandable way. I can understand the logic behind the code. The thing wich really going me crazy is the implementation of the XML RPN. I will check the solution and reply tomorow. Many thanks Bill!

IntruderPL
 

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
Oushhhhhhh! :eek:
Are you a teacher in RL Bill? :) You explained me the whole thing in fully understandable way.

I used to teach "Introduction to Computer Science" at the University of Florida, Gainesville Campus back around a hundred years ago, or at least it seems that long... :D

As a priest, I've always been a teacher! :rotfl:
 
Messages
23
Country
poland
I knew it! :)
Of course, your code works perfectly. I should never say like "I will give it a try", rather I should say "I will change my code as you suggest, Master!" ;)

The next issue I am gonna fight against is a blinking warning lights. I need two different codes - one for fire warning light and second one for general warning light activated when engine is reversed (plus pulsating sound when reverser is activated in the air). I saw similar problem (blinkning land. lights of a chooper?) here and I guess that there is something to do with time variable, but I didnt start yet. I hope both of the codes shouldn't be hard to write and will post them when I begin the fighting.

Thank you very much Bill! :)
 

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
I have this posted at the top of my modeldef.xml file as a reminder:

Code:
<!--
With this universal code it's very simple to control not only the length of the cycle but the frequency of the 
blink itself:
Pseudocode:<Visble>(P:Absolute time,seconds) "seed" % "blink lapse" > !</Visible>
The seed parameter is the total length of the blinking cycle. For example, if you want something to blink on every 
second, you use 1, if you want it blink every half a second, use 0.5 , every two seconds, 2 ,etc.

For each seed, you can determine how long would be the duration of both the visible and invisible part.
Then:
(P:Absolute time,seconds) 1 % 0.5 > ! 
this will make the visible and invisible parts of half a second both.
(P:Absolute time,seconds) 1 % 0.7 > ! 
this will make the visible part 70% of the cycle (0.7 secs) and invisible parts of 30 % (0.3 secs).
(P:Absolute time,seconds) 0.5 % 0.25 > ! 
this will make the visible and invisible parts a quarter of second both.
You can invert the cycle by removing the "!" char.
-->

As a practical example, here is the script I use to "double-flash" custom strobe lights for one of my current projects. Note that it uses two separate timers. The "outer timer" controls the frequency of the strobe. The "inner timer" causes the "strobe" to flash twice in quick succession.

Code:
    <!-- STROBE LIGHT FLASHER -->
    (A:LIGHT STROBE,bool)
    (A:ELECTRICAL MASTER BATTERY,bool)
    and
    if{
         (P:Absolute time,seconds) 2 % 0.4 > !
         if{
              (P:Absolute time,seconds) 0.2 % 0.1 > !
              if{ 1 (>L:B737_Strobe,bool) }
             els{ 0 (>L:B737_Strobe,bool) }
           }
      }

Here is script for a simpler beacon light:
Code:
    <!-- BEACON LIGHT FLASHER -->
    (A:LIGHT BEACON,bool)
    (A:ELECTRICAL MASTER BATTERY,bool)
    and
    if{
        (P:Absolute time,seconds) 2.0 % 1.0 > !
          if{ 1 (>L:B737_Beacon,bool) }
         els{ 0 (>L:B737_Beacon,bool) }
    }
 
Last edited:
Messages
23
Country
poland
I will repeat myself - your code works perfect, Bill! Thanks a milion!
I've used an example from the remind notes, as below:


Code:
	<PartInfo>
		<Name>AN28_ANN_RightEngFire_Light</Name>
		<Visibility>
                                 <Parameter>
                                        <Code>
					(A:ENG ON FIRE:2, bool) 0 &gt;
					(A:CIRCUIT GENERAL PANEL ON, bool)
					(P:Absolute time,seconds) 0.5 % 0.25 >
					and
					and
					if{ 1 } els{ 0 }
                                         </Code>
                                </Parameter>
                           </Visibility>
		<MouseRect>
			<TooltipText>Right Eng Fire</TooltipText>
			<Cursor>Hand</Cursor>
		</MouseRect>
    </PartInfo>

By the way, do you think that closing if{ 1 } els{ 0 } is needed to avoid any problems? Would the simpler example works as well?

Code:
                <Code>
					(A:ENG ON FIRE:2, bool)
					(A:CIRCUIT GENERAL PANEL ON, bool)
					(P:Absolute time,seconds) 0.5 % 0.25 >

                </Code>

and last but not least question today - is anyone know which variable makes possible to detect turboprop engine being in reverse state? I have tried several but with no luck :/

Radek Koterbski
vel Intruder
 
Last edited:

n4gix

Resource contributor
Messages
11,674
Country
unitedstates
If including it works properly, why change? In any case your example would not work because you deleted the two joiner evaluators "and and" which tie the three conditions into a complete expression.

As for the reversed turboprop condition, I have no idea whatever if that's even possible. ;)
 
Messages
23
Country
poland
As for the reversed turboprop condition, I have no idea whatever if that's even possible. ;)

I have found out a workaround here. You can determine under which condition the turboprop is running by checking at which angle its blades are at that moment. Example:

Code:
	<PartInfo>
		<Name>AN28_ANN_LeftEngReversed_WarnLight</Name>
		<Visibility>
            		<Parameter>
                		<Code>
					(A:PROP BETA:1, degrees) -5 &lt;
					(A:CIRCUIT GENERAL PANEL ON, bool)
					(P:Absolute time,seconds) 0.5 % 0.25 >
					and
					and
					if{ 1 } els{ 0 }
                		</Code>
            		</Parameter>
        	</Visibility>
		<MouseRect>
			<TooltipText>Reverse Eng</TooltipText>
			<Cursor>Hand</Cursor>
		</MouseRect>
    	</PartInfo>

Radek Koterbski
vel IntruderPL


PS. I'm gonna love this "ah-ha" moments ;) Thanks Bill, surprisingly you pushed me into right track in this one.
 
Last edited:
Messages
23
Country
poland
Well, I met another issue. This time it's related to ADI. Whenever I lean (bank?) the AC from left to right the ADI's ball doesn't do the same. Instead of it go opposite. Below the code of the ADI I use and a switch that activate the ADI.


Code:
	<PartInfo>
		<Name>AN28_CPADI_bank</Name>
		<AnimLength>360</AnimLength>
		<Animation>
			<Parameter>
				<Code>
					(L:CP_ADIInd_SW, enum) 1 ==
					if{ (A:ATTITUDE CAGE,bool) 1 &lt; (A:ATTITUDE INDICATOR BANK DEGREES, degrees) dnor }
					els{ 90 }
				</Code>				
				<Lag>100</Lag>				
			</Parameter>
		</Animation>
		<MouseRect>
			<TooltipID>TOOLTIPTEXT_BACKUP_ATTITUDE_INDICATOR_BANK_PITCH</TooltipID>
		</MouseRect>
	</PartInfo>

Switch code:

Code:
	<PartInfo>
		<Name>AN28_OVR_CPADI_SW</Name>
		<AnimLength>2</AnimLength>
		<Animation>
			<Parameter>
				<Code>
					(L:CP_ADIInd_SW, enum)
				</Code>
				<Lag>200</Lag>
			</Parameter>
		</Animation>
		<Visibility>
			<Parameter>
				<Code>
					(L:RightPanelLight_SW, enum) 0 &gt;
					(A:CIRCUIT GENERAL PANEL ON, bool) 0 &gt;
					and
					(L:CP_ADIInd_SW, enum) 1 ==
					and
					if{ 1 } els{ 0 }
				</Code>
			</Parameter>			
		</Visibility>
		<MouseRect>
			<Cursor>Hand</Cursor>
			<TooltipText>Right Main ADI Switch</TooltipText>
			<MouseFlags>LeftSingle+RightSingle+Wheel</MouseFlags>
			<CallbackCode>
				(M:Event) 'RightSingle' scmp 0 == if{ (L:CP_ADIInd_SW, enum) -- 0 max (>L:CP_ADIInd_SW, enum) } 
				(M:Event) 'LeftSingle' scmp 0 ==  if{ (L:CP_ADIInd_SW, enum) ++ 1 min (>L:CP_ADIInd_SW, enum) } 
				(M:Event) 'WheelUp' scmp 0 == if{ (L:CP_ADIInd_SW, enum) ++ 0 max (>L:CP_ADIInd_SW, enum) } 
				(M:Event) 'WheelDown' scmp 0 == if{ (L:CP_ADIInd_SW, enum) -- 1 min (>L:CP_ADIInd_SW, enum) }
			</CallbackCode>
		</MouseRect>
	</PartInfo>

EDIT: I should add that ADI pitch animation is attached to the ball, which is linked to small tiny poly (parent) positioned inside the ball. The ADI bank animation is attached to the poly. The bank animation is keyframed every 90 degrees, from 0 degrees (level position) CW up to 359 degrees.

I will apreciate any help.

Radek Koterbski
vel IntruderPL

EDIT: Problem solved. Probably the solution was removing a switch linked with ball by code (Attitude cage, bool). Everything works nicely.
 
Last edited:
Top