* Since the exported C functions just take an explicit 'this' parameter
and call the corresponding function, we can just make it contractual
via a virtual interface that the pointer can be dereferenced.
* The old code in m_RangeMax/m_RangeMin setters wasn't doing proper
epsilon enforcing so min=max could end up happening. It's easier to
set both at once (this is all we care about anyway) so that it does
properly make the min and max distinguishable.
* There were two bug reports of NullReferenceException on line:
hoverWin = m_HoverNode.OwnerView;
* Which doesn't make sense since m_HoverNode must be non-null to go by
the lines above, and all the callbacks should run on the UI thread so
it can't be a race.
* Caching locally and checking for OwnerView/ListView being valid might
fix the crash. Hopefully!
* Tweaked flycam a bit too, but not much.
* Refactored the API/C# side camera classes to avoid exposing a ton of
stuff just to do relative rotations in the arcball via quaternions.
* The arcball lookat position can also be dragged with alt-click or
middle click.
* Also supports other elements as position not just magically-selected
"POSITION" element.
* Should mean the 'target' of the render target will be selected by
default now when clicking to an event, without annoyingly switching
away from what you were looking at.
* This fixes shader editing when the entry point file wasn't the first
in the list.
* Might need better detection of the main file than just searching for
the entry point substring - could produce false positives in other
files in a comment or #define or something similar?
* An array of resources like SamplerState foo[8]; or Texture2D blah[8];
show up as one entry in the reflection data, so need to be expanded
out to several entries.
* Normally it's OK to overlap two resources in the same bind, as long
as only one gets used - this doesn't matter to us since only the used
one will show up in the reflection data. Unless there's an array e.g:
SamplerState foo[8] : register(s0); // [0] and [5] used;
SamplerState bar : register(s3);
in which case foo[] appears in the reflection data for the sake of [0]
and [5], and bar will appear too (causing an overlap between foo[3]
and bar. Since we know the reflection data is unambiguous, we
prioritise individual entries over array entries by listing them
first and using the first match for any bindpoint.
* Still leaving some upper limit so that typos don't result in a zoom
level of something crazy.
* This also allows 'fit to texture' to zoom in more, but I'm OK with
that.