Skip to content

Commit 3b07b27

Browse files
committed
Faster emit-based reading/writing of camera fields
1 parent 87a884d commit 3b07b27

File tree

4 files changed

+105
-21
lines changed

4 files changed

+105
-21
lines changed
2 KB
Binary file not shown.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
VirindiHelpers.DynamicEmitFields
3+
Copyright (C) 2017 Virindi
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
using System;
19+
using System.Reflection;
20+
using System.Reflection.Emit;
21+
22+
namespace VirindiHelpers
23+
{
24+
static class DynamicEmitFields
25+
{
26+
public delegate T delCreateDynamicInstanceFieldGet<T, Cls>(Cls c);
27+
public static delCreateDynamicInstanceFieldGet<T, Cls> CreateDynamicInstanceFieldGet<T, Cls>(string fieldname)
28+
{
29+
string newname = string.Format("__DynGet__{0}__{1}", typeof(Cls), fieldname);
30+
31+
FieldInfo fi = typeof(Cls).GetField(fieldname, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
32+
if (fi == null)
33+
throw new ArgumentException ("Instance field not found.", "fieldname");
34+
if (typeof(T) != fi.FieldType)
35+
throw new ArgumentException ("Instance field is of the wrong type.", "fieldname");
36+
37+
DynamicMethod temp = new DynamicMethod(newname, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(T), new Type[] { typeof(Cls) }, MethodBase.GetCurrentMethod().DeclaringType, true);
38+
39+
ILGenerator gen = temp.GetILGenerator();
40+
gen.Emit(OpCodes.Ldarg_0);
41+
gen.Emit(OpCodes.Ldfld, fi);
42+
gen.Emit(OpCodes.Ret);
43+
44+
delCreateDynamicInstanceFieldGet<T, Cls> ret = (delCreateDynamicInstanceFieldGet<T, Cls>)temp.CreateDelegate(typeof(delCreateDynamicInstanceFieldGet<T, Cls>));
45+
46+
return ret;
47+
}
48+
49+
public delegate void delCreateDynamicInstanceFieldSet<T, Cls>(Cls c, T val);
50+
public static delCreateDynamicInstanceFieldSet<T, Cls> CreateDynamicInstanceFieldSet<T, Cls>(string fieldname)
51+
{
52+
string newname = string.Format("__DynSet__{0}__{1}", typeof(Cls), fieldname);
53+
54+
FieldInfo fi = typeof(Cls).GetField(fieldname, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
55+
if (fi == null)
56+
throw new ArgumentException ("Instance field not found.", "fieldname");
57+
if (typeof(T) != fi.FieldType)
58+
throw new ArgumentException ("Instance field is of the wrong type.", "fieldname");
59+
60+
DynamicMethod temp = new DynamicMethod(newname, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, null, new Type[] { typeof(Cls), typeof(T) }, MethodBase.GetCurrentMethod().DeclaringType, true);
61+
62+
ILGenerator gen = temp.GetILGenerator();
63+
gen.Emit(OpCodes.Ldarg_0);
64+
gen.Emit(OpCodes.Ldarg_1);
65+
gen.Emit(OpCodes.Stfld, fi);
66+
gen.Emit(OpCodes.Ret);
67+
68+
delCreateDynamicInstanceFieldSet<T, Cls> ret = (delCreateDynamicInstanceFieldSet<T, Cls>)temp.CreateDelegate(typeof(delCreateDynamicInstanceFieldSet<T, Cls>));
69+
return ret;
70+
}
71+
}
72+
}
73+

ProbeControlRoom/ProbeControlRoom.cs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ public class ProbeControlRoom : MonoBehaviour
2525
bool SunIsEnabled = true;
2626

2727
//Stuff to mess with
28-
private static System.Reflection.FieldInfo field_internalcamera_currentPitch = null;
29-
private static System.Reflection.FieldInfo field_internalcamera_currentRot = null;
30-
private static System.Reflection.FieldInfo field_internalcamera_currentZoom = null;
28+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldGet<float, InternalCamera> field_get_internalcamera_currentPitch;
29+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldGet<float, InternalCamera> field_get_internalcamera_currentRot;
30+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldGet<float, InternalCamera> field_get_internalcamera_currentZoom;
31+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldSet<float, InternalCamera> field_set_internalcamera_currentPitch;
32+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldSet<float, InternalCamera> field_set_internalcamera_currentRot;
33+
static VirindiHelpers.DynamicEmitFields.delCreateDynamicInstanceFieldSet<float, InternalCamera> field_set_internalcamera_currentZoom;
3134
bool hassavedlookangles = false;
3235
float savedpitch = 0f;
3336
float savedrot = 0f;
@@ -78,12 +81,19 @@ public class ProbeControlRoom : MonoBehaviour
7881

7982
static void GetFields()
8083
{
81-
if (field_internalcamera_currentPitch == null)
82-
field_internalcamera_currentPitch = typeof(InternalCamera).GetField ("currentPitch", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.SetField | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
83-
if (field_internalcamera_currentRot == null)
84-
field_internalcamera_currentRot = typeof(InternalCamera).GetField ("currentRot", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.SetField | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
85-
if (field_internalcamera_currentZoom == null)
86-
field_internalcamera_currentZoom = typeof(InternalCamera).GetField ("currentZoom", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.SetField | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
84+
if (field_get_internalcamera_currentPitch == null)
85+
field_get_internalcamera_currentPitch = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldGet<float, InternalCamera> ("currentPitch");
86+
if (field_get_internalcamera_currentRot == null)
87+
field_get_internalcamera_currentRot = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldGet<float, InternalCamera> ("currentRot");
88+
if (field_get_internalcamera_currentZoom == null)
89+
field_get_internalcamera_currentZoom = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldGet<float, InternalCamera> ("currentZoom");
90+
91+
if (field_set_internalcamera_currentPitch == null)
92+
field_set_internalcamera_currentPitch = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldSet<float, InternalCamera> ("currentPitch");
93+
if (field_set_internalcamera_currentRot == null)
94+
field_set_internalcamera_currentRot = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldSet<float, InternalCamera> ("currentRot");
95+
if (field_set_internalcamera_currentZoom == null)
96+
field_set_internalcamera_currentZoom = VirindiHelpers.DynamicEmitFields.CreateDynamicInstanceFieldSet<float, InternalCamera> ("currentZoom");
8797

8898
if (method_vessellabels_enablealllabels == null)
8999
method_vessellabels_enablealllabels = typeof(VesselLabels).GetMethod ("EnableAllLabels", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance);
@@ -495,12 +505,12 @@ public bool startIVA()
495505
appLauncherButton.SetTexture (IconDeactivate);
496506
}
497507

498-
if (hassavedlookangles && field_internalcamera_currentPitch != null && field_internalcamera_currentRot != null && field_internalcamera_currentZoom != null) {
508+
if (hassavedlookangles && field_set_internalcamera_currentPitch != null && field_set_internalcamera_currentRot != null && field_set_internalcamera_currentZoom != null) {
499509
ProbeControlRoomUtils.Logger.debug(string.Format("startIVA() - Restoring pitch and rot. {0}, {1}", savedpitch, savedrot));
500510

501-
field_internalcamera_currentPitch.SetValue (InternalCamera.Instance, savedpitch);
502-
field_internalcamera_currentRot.SetValue (InternalCamera.Instance, savedrot);
503-
field_internalcamera_currentZoom.SetValue (InternalCamera.Instance, savedzoom);
511+
field_set_internalcamera_currentPitch(InternalCamera.Instance, savedpitch);
512+
field_set_internalcamera_currentRot(InternalCamera.Instance, savedrot);
513+
field_set_internalcamera_currentZoom(InternalCamera.Instance, savedzoom);
504514
InternalCamera.Instance.Update ();
505515
}
506516

@@ -534,10 +544,10 @@ void ResetCameraToIVA()
534544

535545

536546
//Restore PCRIVA camera
537-
if (hassavedlookangles && field_internalcamera_currentPitch != null && field_internalcamera_currentRot != null && field_internalcamera_currentZoom != null) {
538-
field_internalcamera_currentPitch.SetValue (InternalCamera.Instance, savedpitch);
539-
field_internalcamera_currentRot.SetValue (InternalCamera.Instance, savedrot);
540-
field_internalcamera_currentZoom.SetValue (InternalCamera.Instance, savedzoom);
547+
if (hassavedlookangles && field_set_internalcamera_currentPitch != null && field_set_internalcamera_currentRot != null && field_set_internalcamera_currentZoom != null) {
548+
field_set_internalcamera_currentPitch(InternalCamera.Instance, savedpitch);
549+
field_set_internalcamera_currentRot(InternalCamera.Instance, savedrot);
550+
field_set_internalcamera_currentZoom(InternalCamera.Instance, savedzoom);
541551
InternalCamera.Instance.Update ();
542552
}
543553

@@ -627,10 +637,10 @@ public void Update()
627637
//Save where the camera was looking.
628638
//We have to do this here because if the part is shut down,
629639
//we don't have time to get it before it is lost.
630-
if (field_internalcamera_currentPitch != null && field_internalcamera_currentRot != null && field_internalcamera_currentZoom != null) {
631-
float newpitch = (float)field_internalcamera_currentPitch.GetValue (InternalCamera.Instance);
632-
float newrot = (float)field_internalcamera_currentRot.GetValue (InternalCamera.Instance);
633-
float newzoom = (float)field_internalcamera_currentZoom.GetValue (InternalCamera.Instance);
640+
if (field_get_internalcamera_currentPitch != null && field_get_internalcamera_currentRot != null && field_get_internalcamera_currentZoom != null) {
641+
float newpitch = field_get_internalcamera_currentPitch(InternalCamera.Instance);
642+
float newrot = field_get_internalcamera_currentRot(InternalCamera.Instance);
643+
float newzoom = field_get_internalcamera_currentZoom(InternalCamera.Instance);
634644

635645
//Note that if the PCRIVA got broken, these are zero.
636646
if (newpitch != 0f || newrot != 0f)

ProbeControlRoom/ProbeControlRoom.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<Compile Include="ProbeControlRoomPart.cs" />
6161
<Compile Include="ProbeControlRoomUtils.cs" />
6262
<Compile Include="ProbeControlRoomSettings.cs" />
63+
<Compile Include="DynamicEmitFields.cs" />
6364
</ItemGroup>
6465
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
6566
<PropertyGroup>

0 commit comments

Comments
 (0)