Tag: plugins

Lego Brick Code

When Sergio first proposed generic instruments, his model was “lego bricks”. The idea was to provide a number of very basic parts for panel makers and let panel makers mix and match. The result would be huge flexibility for airplane authors without code bloat.

The problem with non-generic instruments is that there is such a huge variety of behavior among airplanes…if Plane-Maker were to have options for every possible plane, the “special equipment” screen would require 3000 tabs and be completely unusable. Hence the need for a smaller unit of modeling: the lego brick.

The prop disc is the first feature I have done that is meant to be used only by a plugin, e.g. “lego brick” code. The X-Plane systems code sometimes suffers from the same “code bloat” problem as the instruments: a ton of very specific, very tweaky behaviors that interact in strange ways and become very difficult to manage. It’s not that the systems code is bad code – it’s that the scope of the problem is simply too large. That is, you can’t expect X-Plane to cleanly simulate the systems of every airplane ever in a ton of detail through an a la carte menu of check-boxes.

The idea of the prop disc is: someone (LR or otherwise) can write a plugin that encodes a certain style of prop disc. That plugin can then be picked up and moved around like a generic instrument between planes (perhaps with a corresponding text file to control it).

If someone else comes up with a different/better prop-disc algorithm, compatibility isn’t an issue…that person writes a new prop disc plugin and the airplane author selects the one desired. Think of it as sort of a portable flight model that stays with your plane.

So we win in three ways:

  • Anyone can write the prop disc algorithm, not just LR.
  • The code lives with the plane, to avoid compatibility problems.
  • More than one plugin can exist, giving authors an a la carte menu.

That’s the theory at least.

Posted in Aircraft, Development by | 2 Comments

Tweaking the Prop Disc in 940

X-Plane 940 allows plugins to customize the prop disc. Details here on the wiki.

I put these datarefs in so that modelers wouldn’t have to try to model prop discs with OBJs. The problems with prop discs are many:

  • They need to be billboarded, and X-Plane does not provide datarefs for manual billboarding inside an airplane (particularly not to the engine’s coordinate system, which can be transformed by all sorts of fun stuff).
  • They often need variable translucency, which OBJ does not have.
  • They cause all sorts of depth buffer errors, which OBJs cannot manage.

In short, prop discs are weirdly special-cased enough that I thought it would be better to provide a general set of parameter datarefs for prop discs and let X-Plane do the drawing.

These options are not available in Plane-Maker. Why not? That’ll be my next post.

Posted in Aircraft, Development by | 1 Comment

Where Do I Find the 930 Datarefs

The dataref documentation on the X-Plane SDK website is updated for each release of X-Plane 9.

X-Plane 930 has not yet been released. It is a “release candidate” but since we haven’t signed off on it yet, 922r1 is still the most current real release of X-Plane, and it’s what users get when they update without asking for a beta. So the website has 922 datarefs.

Since version 9, every release of X-Plane (including betas and RCs) has a copy of datarefs.txt in the plugins folder that is correct for that release. In other words, the docs that ship with X-Plane and the sim itself are always in sync.

So for now use datarefs.txt in the 930 RC 2 plugins folder! When 930 goes final, the website will be updated.

Posted in Development by | 4 Comments

Datarefs Vs. Commands IV: Duplication

In my previous posts I have tried to explain the difference between commands and datarefs, and when you might use each.  To review:

  • A dataref represents information. You can always read it, and you might be able to change it.
  • A command represents an action.  You can always invoke the action, but you can’t tell if it worked without looking at a dataref.

So…why is there so much overlap and duplication?

Dataref Vs. Dataref
There is duplication in the datarefs because we don’t delete old datarefs when we add newer, improved ones. The old datarefs stay in place to keep old plugins working. Here are a few reasons why we’ve added new datarefs:
  • The cockpit2/ and flightmodel2/ sections were added as a new, simpler, easier to use interface for authors in version 9.  (Read more here and here and here.)
  • In some cases, the old dataref was a bit-field while the new one is a simple integer. While plugins can use bitfields, modelers cannot animate using bit fields.
  • In some cases, the old dataref did not represent a clean view of the data. Some old datarefs exposed X-Plane internal structures that are not appropriate for long-term use.

To see this in action, let’s look at the autopilot.  How many ways are there to set the autopilot mode?

  1. sim/cockpit/autopilot/heading_mode. This is the original heading mode, and it is marked deprecated, because it exposes a bunch of internal X-Plane autopilot values.
  2. sim/cockpit/autopilot/autopilot_state. This is the ideal autopilot dataref for plugins. It provides all functions, but since it is a bit-field it is not useful for authors.
  3. sim/cockpit2/autopilot/heading_mode. This is a clone of the original heading_mode into the cockpit2 domain. Honestly I am not sure how it got there – I know it was me who put it there, but it sure is a dumb idea; the original dataref is deprecated, so it was stupid of me to duplicate it!
  4. sim/cockpit2/autopilot/heading_state. This is coming in 930 and provides a heading-state enum set appropriate for authors…basically an enum that matches the two heading bits of the autopilot_state dataref that programmers were using.

How do you sort through this? Three rules of thumb:

  • Try to use sim/cockpit2 and sim/flightmodel2 when possible.
  • More recent datarefs are usually better.
  • Use the most useful dataref you can find.
Commands Vs. Commands
Sometimes there is some duplication of commands, e.g.
sim/engines/carb_heat_on                           Carb heat on.
sim/engines/carb_heat_off                          Carb heat off.
sim/engines/carb_heat_toggle                       Carb heat toggle.
Here it’s a lot more obvious why there are multiple commands: they affect the carb heat in multiple ways. Typically this is done because commands are mapped to joysticks and other USB hardware; some hardware generates a button press when a command is toggled, but some hardware generates two commands, one for the off and one for the on position.
The rule of thumb is: use the command that gives you the action you want.
Commands Vs. Datarefs
Very often there will be a command and a writable dataref.  Typically we need them both:
  • The command is needed to let users set up their joystick and keyboard.
  • The dataref predates version 9 – writing it was the only way to invoke an action.

Newer datarefs are more likely to be read-only, as we put new “changing the sim” functionality into commands.  To go back to our autopilot example, we have on command: sim/autopilot/heading that lets us arm heading mode.  This command is probably preferable to any of the datarefs for changing the autopilot state.

My previous post discusses writing to a dataref. vs. actuating a command in more detail.
Posted in Aircraft, Development, Modeling by | 4 Comments

Datarefs Vs. Commands III: What Is My command Doing?

It turns out that understanding what a command is doing gets really complicated.
The key idea to untangling it all is this:
  • Commands have duration, and that duration is the amount of time you “hold down” the button or key that actuates the command.
  • Not all commands do things for the entire duration.
An example will clarify this:
  • When you press and hold down the ‘p’ key to pause the sim, the sim pauses (or unpauses) instantly the moment you press the p key.  Holding the p key down for a long time does not change this.  Pause is a “momentary” command.
  • You have to keep the starter button/key held down for a few seconds to start an engine. If you press it and release it, the starter motor will only run for a fraction of a second, which is not enough time to start an aircraft engine.  Engine start is a “duration” command.
Virtual Datarefs
A “virtual dataref” isn’t really a dataref at all – it’s a string you can enter into an OBJ or generic instrument that looks like a dataref, but actually is something else.  There is one “set” of virtual datarefs in X-Plane right now.
In X-Plane, you can enter

CMND=some/command/name

into a generic instrument or obj animation – this creates a “virtual dataref” around the command’s “activation status”.  The virtual dataref acts like a read-only integer-type dataref whose value is 0 if the command is not being pressed right now and 1 if it is.
For example, if you animate a push button using CMND=sim/starters/engage_starter_1 (key framing the animation to be “out” when the virtual dataref is 0 and 1 when it is in) then you will have a button that appears to be pressed whenever the starters are engaged.  This will happen no matter how the starter is engaged – your animation will happen whether the user presses a joystick button, holds down a key, clicks on a manipulator, or a plugin runs the command.
Basically, virtual datarefs that provide “activation status” of commands exist so that you can animate the buttons in your virtual cockpit to match what the user is doing with the mouse, keyboard, etc.  These datarefs are read-only; use trigger generic instruments and command manipulators to actually run the command.
For Programmers
In that last section I pointed out that a virtual dataref is not a real dataref at least 3 times. Why am I harping on this?  Well, programmers, you cannot use XPLMFindDataRef to access virtual datarefs yourself.  Sorry.
Virtual datarefs exist to give authors of OBJs and panels access to command activation status, something they would not normally have.
Plugin programmers don’t need this – if you are programming a plugin you simply use XPLMRegisterCommandHandler and you will be told when the command is being actuated and released.  Using a command handler is a lot more efficient than reading a dataref because you will receive a call only when the command is pressed, instead of having to check the dataref value every frame.  If you need to monitor a lot of commands, the callbacks are a lot more efficient.
Command Activation Is Not The Same As System Activation
Let’s go back to the case of the “pause” command and review.  Here’s what we know about the pause command.
  • The command sim/operation/pause_toggle will change the sim’s pause state.  The instant this command is pressed, the sim will pause (if it is runnning) or unpause (if it is paused).
  • Holding down the sim/operation/pause_toggle command has no effect beyond its initial press. Hold it down for an hour, it doesn’t matter.
  • The virtual dataref CMND=sim/operation/pause_toggle tells you if the pause command is being held down at any instant.
Here’s what we know about the pause dataref.
  • The dataref sim/time/paused is 1 if the sim is paused, 0 if it is not.
  • This dataref cannot be written!
So here’s what I mean when I say: command activation is not the same as system activation.
  • CMND=sim/operation/pause_toggle tells you if the pause button is being held down.
  • sim/time/paused tells you if the sim is actually paused or not.
  • They are simply not the same!
This becomes important when you start to model the buttons in airplanes.  Take for example an autopilot button for altitude hold.  In many planes, the button can be pushed in, and the moment you do, the altitude hold “arm” light will turn on.  Keep the button held in and it doesn’t have any more effect.  Altitude hold arm is a momentary command, but it has a system status indicator light.
I receive a number of questions about how to model this – and the answer is: take advantage of the fact that command activation (is the button pushed in) and system activation (is the light on) are not the same.
  • You would use a read-only dataref for the autopilot state to turn on the indicator light.  (There are two ways to do this: use ATTR_light_level to turn a _LIT texture on and off, or use panel texture and map a generic instrument like a rotary or an annunciator.)
  • You would use a command to make the button work.  Probably you’d use a command manipulator on the button mesh.
  • You would key frame the button’s animation based on the virtual dataref wrapped around the command you are using with the manipulator.
The result will be a button that lights up when the AP is armed but pushes in while it is being pressed (whether via the mouse in the 3-d cockpit or a joystick button press or a keyboard button press).
In my final post, I’ll comment on how much overlap there is between datarefs and commands.
Posted in Aircraft & Modeling, Development, Modeling by | Comments Off on Datarefs Vs. Commands III: What Is My command Doing?

Scripting: A Line In the Sand

I thought I had already blogged about this, but I can’t find the old posts, so here goes. The big question: why can’t we have “X” in the OBJ file format or as part of generic instruments?

I get a lot of requests for “more power” in the OBJ or generic instrument system – the ability to play sounds, to do simple math operations on datarefs, more show-hide filters, the ability for a generic instrument to change a dataref in response to another dataref instead of a mouse click.

And invariably I say “No! Go write a plugin!”, which I realize is a fairly rude thing to say to a non-programmer. First, let me explain why I say no, and then what we can do about this.

Keeping Systems Separate

These feature requests fall into two broad categories: “systems programming”, which is really anything that has a side effect (play a sound, change a dataref, apply some logic), and “visualization” (e.g. a user needs more flexibility to better visualize the sim’s state.

I definitely do not want any kind of “systems modeling” code inside OBJs or generic instruments. To give a trivial example: imagine that you could make a generic instrument that would set the generators to on when the landing gear is raised.

What then happens if this generic instrument is off the bottom of the screen when the landing gear is raised? Does the generic instrument get to perform its logic? Both OBJs and generic instruments are fundamentally “visualization” systems – both will short-circuit for performance when they are not visible. If we put systems modeling code into them, then the sim has to evaluate a potentially large number of otherwise unimportant (non-visible) objects and instruments to do system behaviors.

In computer programming, there is the notion of a “model-view-controller” design. The basic idea is to keep the code that changes the model, the model itself, and the code that lets the user see the data model, all separate. Keeping them separate keeps operation consistent – the model does not change its behavior depending on how you look at it, which is very important for consistent simulation.

So for all systems modeling, my answer is always the same: not in viewing code!

Expressions and Visualization

Some requests are simply requests for more visualization complexity – there is only so much you can do with key frames, animation, and a few filters.

I do have to admit that on some level, it is perfectly reasonable to ask for infinite power to visualize data in OBJs and generic instruments.

On the other hand, there would be a real cost to having programming-language complexity in what are otherwise relatively simple-to-use parts of X-Plane (e.g. the simplest model is just an export from ac3d…). My solution for both problems (systems and visualization) is a scripting system, but in the case of visualization, it is about not reinventing the wheel and keeping complexity limited to one place (the scripting system).

Scripting

Plugins have the power to solve all of these problems – they can change almost any aspect of the sim. But they are also very difficult to create; you need to be a programmer who knows a language like C or Pascal, and you need to know how to use the development tool for each platform you want to support. That’s a huge amount of specialized knowledge just to customize a few systems.

Basically we need to have a line in the sand. At some point, when the systems to visualize information (OBJ, generic instruments) are not powerful enough, we need to make programming easier, rather than make modeling and authoring more complex.

What we need is a scripting system. The scripting system would provide a relatively simple text-file syntax to do simple scripting of systems and instruments for airplanes.

Such a scripting system should be implemented as an open source plugin; it should not be built into X-Plane. The advantage of this would be:

  • Anyone could improve or add features to such a scripting system, not just Austin and myself.
  • People could freely customize the scripting system as needed for specific projects.
  • By having the code be part of a plugin and not the sim, backward compatibility would be improved – even if the “official” version of the scripting plugin changed, you could always include an older version with your plane that worked exactly the way you want.

Who should work on this scripting system? I don’t know. Probably not me — I am not very good at making simple systems; see also what a complex disaster the panel and instrument system has become!

When a user requests that I add a feature to the generic instrument system, there is an implicit request – that Austin or I take programming time to do the feature. So for now I can only say that if/when I take time to do some of these feature requests, it will be in the form of a scripting system, not as extensions to the generic instrument and OBJ systems. This will give us better long-term compatibility and extensibility (via an open source plugin) and will keep systems modeling code separate from the visualization system.

Posted in Cockpits, Development, Modeling by | 4 Comments

The “Airplane Modeling” Datarefs

I have blogged about this before, but I will try to create one simple explanation of what’s going on with sim/cockpit2 and sim/flightmodel2 datarefs.

Sandy and I (with the help of others who helped compile the list) created “new” datarefs (first released with X-Plane 9) , aimed at airplane modelers. These new sections are:

  1. sim/cockpit2/ which provides a new set of datarefs for cockpit modeling via OBJ animation and generic instruments.
  2. sim/flightmodel2/ which provides a new set of datarefs for airplane exterior modeling via OBJ animation.

These datarefs sometimes include new data that was not available in version 8, and sometimes they simply provide a second dataref with the same information. Why duplicate datarefs? The new datarefs have some special properties, so I wanted to have a complete set of datarefs for modelers with these new properties.

Skip to the end for the rules of thumb on how to use them.

Clean Naming

The new datarefs are designed to have longer, less confusing names; the old datarefs contained a lot of abbreviations – potentially acceptable for programmers (who are used to seeing things like fstat and chgrp on a regular basis) but not good for modelers who do not speek English as a first language. The new datarefs have long names and are more consistent in their conventions. They also contain complete documentation.

Array Sizes

You will see the array dimension of some of the new datarefs as symbolic constants, e.g. [engine] instead of [8]. This is because the dataref generation system we use knows that these new datarefs sometimes track the maximum number of parts in the aircraft structure. This tagging means that it is much simpler for Sandy and I to adjust the datarefs when Austin increases part maximums.

With the old datarefs, if Austin allows for 10 engines, Sandy and I must search for every [8] dataref and decide if it must be [10] – some will be per-engine and need to change, some will be per-battery and will not! With the new system, we simply redefine the “engine” constant to 10 and the datarefs adjust.

(Note that if your plugin really needs to run dynamically with any number of engines, the best thing to do is to read the array size using XPLMGetDatavX.)

Failure Support

There are two ways to view a dataref: before system failures (such that the dataref reflects simulated physical reality) and after system failures (such that the dataref reflects pilot indications). For example, when the pitot tube ices up, the pre-failure airspeed reflects how fast you are flying; the post-failure airspeed reflects how much crud is in your pitot tube.

Pre-failure datarefs are appropriate for animating the exterior of the airplane. For example, if the gear indicator light fails but the gear is working, you want to animate your landing gear based on the real (pre-failure) gear position, so that the gear really does look like it’s down from an outside view.

Post-failure datarefs are appropriate for animating the cockpit. For example, you want to use that post-failure indicated airspeed for your air speed indicator, so that pitot ice will affect your generic instruments and animations, as well as the built-in instruments.

The new datarefs are designed to clearly provide two different views:

  • sim/cockpit2/ are all post-failure whenever possible, and are thus appropriate for cockpit modeling.
  • sim/flightmodel2/ are all pre-failure, and thus are appropriate for external airplane modeling.

Be careful not to swap them! You should always be using sim/flightmodel2/ for your aircraft and sim/cockpit2/ for your cockpit. If the dataref you need is in one and not the other, email me and I will add it to the right place.

Correct Multiplayer Behavior

The older datarefs all return data about the user’s airplane. However if you build an object, attached to an ACF, and that ACF is loaded for a multiplayer plane, you will get incorrect results — the user will see his own plane’s actions visualized on the multiplayer plane.

The new sim/cockpit2/ and sim/flightmodel2/ datarefs handle this case correctly: they return data about whichever airplane is being drawn. Thus if your object is attached to airplane number 5 in a multiplayer session, that’s the airplane that will animate your control surfaces.

(Plugin developers – outside airplane drawing, these datarefs return information about the user’s flight.)

For this reason, you should always use sim/cockpit2/ and sim/flightmodel2/ – not the older sim/cockpit and sim/flightmodel/ datarefs. If the dataref you want is only in the old sections but not the new ones, email me!

What Dataref Do I Use?

Here’s the rule of thumb:

  • If you are targeting X-Plane 6/7/8, you must use sim/cockpit and sim/flightmodel, otherwise
  • If you are targeting X-Plane 9, use sim/cockpit2 for your generic instruments and 3-d cockpit. Use sim/flightmodel2 for your attached objects.

That’s all there is to it!

Posted in Aircraft, Aircraft & Modeling, Cockpits, Development, Modeling, Panels by | Comments Off on The “Airplane Modeling” Datarefs

Spam My Wiki, Please

User Rs2Play is now the first user to be banned from the X-Plane Wiki.  WikiMedia has some automatic features, like banning all associated IP addresses with a banned user, so if you find yourself kicked from the Wiki in error, email me and I will fix it.  (This would only happen if you were in the same shared IP pool as the user in question.)  Thanks to the users who immediately removed the spam while I was out of the office.

(If we have more spam, I can promote a few users to admin status to ban spammers faster, but so far we have had only one case.)
Unfortunately the situation with the X-Plane SDK Wiki is not as good.  The problem is that the SDK Wiki does not use MediaWiki – it uses phpwiki, so we do not have the rich set of user admin tools that MediaWiki comes with out of the box.  There is currently a user who is (for some reason) attacking the user database by registering fake email addresses over and over.  I do not know what the user hopes to accomplish, other than wasting my time.
The unfortunate side effect is to leave the SDK Wiki user database in a state of chaos.  When I have time, I will be adding some new features to the user signup code and trying to clean out the user base.
Why are we not using MediaWiki for the SDK?  Well, besides history (we used what we found at the time), the SDK Wiki’s code is customized to integrate the SDK development tools with the Wiki itself.  This is how you get the latest documentation and user generated content on one page when you look up an XPLM function.
There is no scenery system Wiki – something I have debated a bit.  At this point though I am more concerned with getting the scenery tools out than with updating the documentation; once we have a more complete tool set, then I can ask the question “can users figure out how to use these tools.”
Posted in Development, News by | 1 Comment

Engine Modeling and Autopilot

Two random and unrelated notes:

First, RC4 is going out as is, despite the engine modeling changes being incomplete. Basically we now have a more sane approach to the engines themselves, but no FADEC control. FADECs are on the short list for the next update. Sometimes we just run out of time – not every release can have everything.

Second, a note on autopilot customization – I am party to a fair number of questions about whether the plugin system can be used to make subtle changes to the autopilot logic. The answer is of course: no. If you really want something different for an autopilot, you’d have to replace the entire “top-half” set of logic and drive the flight directors yourself – in this situation you are responsible for:

  • All modes and mode changes based on conditions.
  • The actual selected flight envelope to achieve the desired AP setting.

But you are not responsible for driving the trim and yoke, which are done by you setting the flight director.

Why can’t you just override one specific behavior? It’s an issue of infrastructure.

Fundamentally, the autopilot only does a few certain tricks. If it were capable of doing customized behaviors, you’d already see it, in the form of a dataref or (more likely) a Plane-Maker setting. Basically there is no generality to the autopilot that we secretly have inside the code but don’t expose.

Will there be a more general autopilot someday? Maybe – I don’t know, I don’t work on that code. But the plugin system has always aimed to make it possible to do anything, but not necessarily easy. In particular, the plugin system doesn’t aim to make your development easier by recycling the simulator itself as a convenient library of lego bricks. In the end of the day, X-Plane is an application, not a library. If it were a library, that would be lots of fun for third parties, but it is not.

Posted in Development, News by | Comments Off on Engine Modeling and Autopilot

Custom Datarefs for OBJ Animation

I don’t usually blog about plugin issues, but this one falls into limbo, somewhere between plugins, aircraft design and OBJ animation. This is written for plugin developers; if you don’t write plugins, you can tune out.

Plugin Drawing

Plugin drawing is documented in a few tech notes – I strongly recommend reading them all.

The basic idea is this: to draw in a plugin, you register a callback. X-Plane tells you “it’s time to draw” and you draw.

The first rule of drawing callbacks is: you only draw. You don’t do anything else.
The second rule of drawing callbacks is: you only draw. You don’t do anything else.

There are a number of good reasons for this.

  1. You don’t know how many times, or in what order the callbacks will be called! You might be called four times per frame or none. So doing flight model calculations in a draw callback is a bad idea.
  2. Drawing has to be fast. In the drawing code we are trying to stuff the GPU to the gills with work to do. Drawing time is not a good time to go off and do other expensive calculations.When we look at the interaction of the CPU and GPU, we know that the flight model takes some pure CPU time, and we can improve efficiency by queuing an expensive OpenGL operation before we hit that CPU-only phase. If your plugin is doing its real calculations during draw time, our pipelining gets thrown off.
  3. We’re continually increasing the parallelism of the sim via threads to take advantage of multiple cores. But plugins are single threaded by definition. This means that plugin interaction points will (in the future sim) halt parallel operation and slow overall performance. When we design parallel operation, we can try to optimize our design to avoid this “halt” case, but if you are doing something strange (like flight calculations in a draw loop) you’re more likely to fall off the “fast path”.

Surprise

Now here’s the surprising thing: your dataref callback is actually a drawing callback, sort of!

Object datarefs are called back during object drawing. Therefore they have all of the above problems that drawing callbacks have. Here is my recommendation:

If you create a custom dataref that is used by an OBJ for animation, return a cached value from a variable in the dataref, and update that variable from the flight loop.

This avoids the risk of your “systems modeling” code being called more than once per frame, etc.

Posted in Aircraft & Modeling, Development by | 1 Comment