Discussion:
Knob Slider animation action binding incorrectly in multiplayer.
(too old to reply)
Richard Harrison
2017-06-17 18:29:31 UTC
Permalink
I've been working on the F-14 backseat (multiplayer); one of the things
that I've added is a brightness knob.

The first part of the knob animation works correctly. When in
multiplayer the position of the knob (set to the relative path of
sim/model/f-14b/controls/radar-awg-9/brightness) is correctly reading
from
ai/models/multiplayer/sim/model/f-14b/controls/radar-awg-9/brightness
however when I move the knob it is appears to have lost the property
root and instead is writing to the root and updates
sim/model/f-14b/controls/radar-awg-9/brightness - as you can see in the
picture.[1]

I'm fairly sure that this is the problem; I've tried to follow how the
action/binding is created but need help. The XML is below for reference.

Loading Image...

<animation>
<type>knob</type>
<object-name>TID-brightness-knob</object-name>
<property>sim/model/f-14b/controls/TID/brightness</property>
<factor>230</factor>
<center>
<x-m>0.09482</x-m>
<y-m>0.07908</y-m>
<z-m>0.14837</z-m>
</center>
<axis>
<x>-1</x>
<y>0</y>
<z>0</z>
</axis>

<action>
<binding>
<command>property-adjust</command>
<property>sim/model/f-14b/controls/TID/brightness</property>
<factor>0.1</factor>
<min>0</min>
<max>1</max>
<wrap>false</wrap>
</binding>
</action>
</animation>


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

[1] This also manifests as a slightly polluted sim/model as it will have
properties from the multiplayer nodes.
James Turner
2017-06-19 08:03:19 UTC
Permalink
The first part of the knob animation works correctly. When in multiplayer the position of the knob (set to the relative path of sim/model/f-14b/controls/radar-awg-9/brightness) is correctly reading from ai/models/multiplayer/sim/model/f-14b/controls/radar-awg-9/brightness however when I move the knob it is appears to have lost the property root and instead is writing to the root and updates sim/model/f-14b/controls/radar-awg-9/brightness - as you can see in the picture.[1]
I'm fairly sure that this is the problem; I've tried to follow how the action/binding is created but need help. The XML is below for reference.
For other animations, what is the mechanism by which such property paths become ‘relativised’ rather than absolute? I expect that I didn’t know about this case when creating the knob animation, and have missed some piece of logic.

Unless it’s supposed to be automatic / invisible to the animation code, in which case I am clueless.

Kind regards,
James
Richard Harrison
2017-06-19 14:28:41 UTC
Permalink
Post by James Turner
Post by Richard Harrison
The first part of the knob animation works correctly. When in
multiplayer the position of the knob (set to the relative path of
sim/model/f-14b/controls/radar-awg-9/brightness) is correctly reading
from
ai/models/multiplayer/sim/model/f-14b/controls/radar-awg-9/brightness
however when I move the knob it is appears to have lost the property
root and instead is writing to the root and updates
sim/model/f-14b/controls/radar-awg-9/brightness - as you can see in
the picture.[1]
I'm fairly sure that this is the problem; I've tried to follow how
the action/binding is created but need help. The XML is below for
reference.
For other animations, what is the mechanism by which such property
paths become ‘relativised’ rather than absolute? I expect that I
didn’t know about this case when creating the knob animation, and have
missed some piece of logic.
I think the problem is with the bindings; as these use fgcommand to do
the work, which in turn do not have the correct property root from the
model animation context, which results in part of the knob animation
using the relative property and the binding using the root property.

I'm not sure how to fix this at the moment. Simplistically it's just a
case of passing in the relative root; but need to figure out the details.

example call stack for reference..
Post by James Turner
fgfs.exe!do_property_adjust(const SGPropertyNode * arg) Line
407 C++
fgfs.exe!SGCommandMgr::FunctionCommand::operator()(const
SGPropertyNode * arg) Line 57 C++
fgfs.exe!SGBinding::innerFire() Line 92 C++
fgfs.exe!SGBinding::fire(double offset, double max) Line 122 C++
fgfs.exe!fireBindingListWithOffset(const
std::vector<SGSharedPtr<SGBinding>,std::allocator<SGSharedPtr<SGBinding>
Post by James Turner
Post by Richard Harrison
& aBindings, double offset, double max) Line 147 C++
fgfs.exe!KnobSliderPickCallback::fire(bool isShifted,
KnobSliderPickCallback::Direction dir) Line 691 C++
fgfs.exe!KnobSliderPickCallback::buttonReleased(int keyModState,
const osgGA::GUIEventAdapter & __formal, const SGPickCallback::Info *
__formal) Line 597 C++
fgfs.exe!FGMouseInput::doMouseClick(int b, int updown, int x, int
y, bool mainWindow, const osgGA::GUIEventAdapter * ea) Line 596 C++
James Turner
2017-06-19 17:58:03 UTC
Permalink
I think the problem is with the bindings; as these use fgcommand to do the work, which in turn do not have the correct property root from the model animation context, which results in part of the knob animation using the relative property and the binding using the root property.
I'm not sure how to fix this at the moment. Simplistically it's just a case of passing in the relative root; but need to figure out the details.
Your description all makes sense, but again I feel this should be the same for pick animations that use bindings - I’m missing if there is something particular to the knob animation I can fix?

Since all commands are ignorant of the relative paths used for AI, to the best of my knowledge.

Kind regards,
James
Richard Harrison
2017-06-19 23:42:19 UTC
Permalink
Post by James Turner
Post by Richard Harrison
I think the problem is with the bindings; as these use fgcommand to
do the work, which in turn do not have the correct property root from
the model animation context, which results in part of the knob
animation using the relative property and the binding using the root
property.
I'm not sure how to fix this at the moment. Simplistically it's just
a case of passing in the relative root; but need to figure out the
details.
Your description all makes sense, but again I feel this should be the
same for pick animations that use bindings - I’m missing if there is
something particular to the knob animation I can fix?
When I posted I thought it was related just to the knob/slider
animation; it's only since this afternoon that I realised that it
affects all bindings.

I can workaround the bug by calling into a Nasal module that knows the
property root; however I think it needs fixing properly - mainly because
if it is correctly implemented it will allow a much more generic
interface to multiplayer models

In the current case it's just the backseat of an F-14, but I'm starting
to think that there could be a more generic copilot interface by using
Emesary notifications bridged over MP, one that might allow a single
generic dual control model that will work with all craft.
James Turner
2017-06-20 07:51:02 UTC
Permalink
When I posted I thought it was related just to the knob/slider animation; it's only since this afternoon that I realised that it affects all bindings.
I can workaround the bug by calling into a Nasal module that knows the property root; however I think it needs fixing properly - mainly because if it is correctly implemented it will allow a much more generic interface to multiplayer models
In the current case it's just the backseat of an F-14, but I'm starting to think that there could be a more generic copilot interface by using Emesary notifications bridged over MP, one that might allow a single generic dual control model that will work with all craft.
Okay, that’s good that it is generic.

Doing a fix at the command level will take some doing - all the commands operate on the global property root. We would need to add an additional argument to them giving a context (relative root), which can absolutely be done, but needs a little bit of care and consideration, since there are other problems we might wish to solve if doing that.

For example, being able to target different instrument instances (nav radio 1 or 2, or autopilot 1, 2, 3 
.) this way would allow some re-use of bindings, I think. Certainly I’ve had to duplicate bindings purely to adjust the base path to the instrument.

Kind regards,
James
Richard Harrison
2017-06-23 21:02:14 UTC
Permalink
Post by James Turner
Doing a fix at the command level will take some doing - all the
commands operate on the global property root. We would need to add an
additional argument to them giving a context (relative root), which
can absolutely be done, but needs a little bit of care and
consideration, since there are other problems we might wish to solve
if doing that.
I've now implemented the change and will commit shortly once I've done
some more testing.

The solution is, as you said, to add a root parameter to each of the
commands. This can either be a property node, or nullptr to indicate the
global root.

I've thought about the other problems; and essentially the only thing I
could think of was the case where you need to pass in a different root;
which will work - however other changes will be made (e.g. to allow
fgcommand() to pass in a root). The new root argument is ignored by most
of the command implementations, and as such reasonably safe.
James Turner
2017-06-24 07:32:32 UTC
Permalink
I've now implemented the change and will commit shortly once I've done some more testing.
The solution is, as you said, to add a root parameter to each of the commands. This can either be a property node, or nullptr to indicate the global root.
I've thought about the other problems; and essentially the only thing I could think of was the case where you need to pass in a different root; which will work - however other changes will be made (e.g. to allow fgcommand() to pass in a root). The new root argument is ignored by most of the command implementations, and as such reasonably safe.
Okay - how are you finding / injecting the correct root based on the animation’s context?

Kind regards,
James
Richard Harrison
2017-06-24 11:02:17 UTC
Permalink
Post by James Turner
I've now implemented the change and will commit shortly once I've done some more testing.
Okay - how are you finding / injecting the correct root based on the
animation’s context?
It was already passed into the SGBinding constructor (via
readBindingList) as it is used for the conditions, so it was just a case
of adding it to the class and passing it to the command interface.
Loading...