Files
gtav-src/tools_ng/dcc/current/max2012/scripts/pipeline/util/RSdotNet.ms
T
2025-09-29 00:52:08 +02:00

668 lines
20 KiB
Plaintext
Executable File

--
-- Useful functions for things that use DotNet
--
-- Neal D Corbett
-- (Rockstar Leeds)
-- 11/03/2011
--
-- Returns an instance of a DotNet assembly stored in "globVal", compiling it from "source" if that's invalid:
fn RsGetCompiledAssembly name source refList &globVal forceRecompile:false =
(
if forceRecompile or ((not isKindOf globVal dotNetObject) or
(((globVal.GetType()).ToString()) != "System.Reflection.RuntimeAssembly")) do
(
local csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
local compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
-- Add referenced assemblies that the code snippet is 'using'
for item in refList do
(
compilerParams.ReferencedAssemblies.Add item
)
compilerParams.GenerateInMemory = true
local compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
local errors = compilerResults.Errors
if (errors.Count > 0 ) then
(
local errs = stringstream ""
for i = 0 to (errors.Count - 1) do
(
local err = compilerResults.Errors.Item[i]
format "Error:% Line:% Column:% %\n" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
)
MessageBox (errs as string) title: "Errors encountered while compiling C# code"
format "%\n" errs
globVal = undefined
)
else
(
globVal = compilerResults.CompiledAssembly
)
)
if (globVal == undefined) then (return undefined) else (globVal.CreateInstance name)
)
------------------------------------------------------------------------------------------------------------
-- RS_ListViewItemComparer
-- Generates and supplies an assembly for sorting a ListView by its columns
-- (originally found here: http://forums.cgsociety.org/archive/index.php/t-551473-p-2.html)
------------------------------------------------------------------------------------------------------------
global gRsListViewItemComparerAssembly = undefined
fn RS_ListViewItemComparer forceRecompile:false =
(
local source = "
using System;
using System.Windows.Forms;
using System.Collections;
class gpgxListViewItemComparer : IComparer
{
public int column;
public bool reversed;
public gpgxListViewItemComparer()
{
column = 0;
reversed = false;
}
public gpgxListViewItemComparer(int col, bool rev)
{
column = col;
reversed = rev;
}
public int Compare(object x, object y)
{
int ret = 0;
ListViewItem lvx = (ListViewItem)x;
ListViewItem lvy = (ListViewItem)y;
if (column >= 0 && column < lvx.SubItems.Count && column < lvy.SubItems.Count)
ret = String.Compare(lvx.SubItems[column].Text, lvy.SubItems[column].Text);
return reversed ? -ret : ret;
}
}
"
RsGetCompiledAssembly "gpgxListViewItemComparer" source #("System.dll", "System.Windows.Forms.dll") &gRsListViewItemComparerAssembly forceRecompile:forceRecompile
)
------------------------------------------------------------------------------------------------------------
-- RS_NoFocusDotNetForm
-- Generates and supplies a DotNet Form that appears without taking focus automatically
------------------------------------------------------------------------------------------------------------
global gRsNoFocusFormAssembly = undefined
fn RS_NoFocusDotNetForm forceRecompile:false =
(
local source = "
using System;
using System.Windows.Forms;
public class NoFocusForm : Form
{
protected override bool ShowWithoutActivation { get { return true; } }
}
"
RsGetCompiledAssembly "NoFocusForm" source #("System.dll", "System.Windows.Forms.dll") &gRsNoFocusFormAssembly forceRecompile:forceRecompile
)
------------------------------------------------------------------------------------------------------------
-- RS_disableProcessWindowsGhosting
-- Turns off window-ghosting for the current session of Max
------------------------------------------------------------------------------------------------------------
--copied from cgtalk
--http://forums.cgsociety.org/showthread.php?f=98&t=958314&page=2&pp=15
--this turns off window-ghosting for that session of Max
global gRsDisableGhostingAssembly = undefined
fn RS_disableProcessWindowsGhosting forceRecompile:false =
(
local source = "
using System.Runtime.InteropServices;
public class DisableWindowsGhosting
{
[DllImport(\"user32.dll\")]
public static extern bool DisableProcessWindowsGhosting();
}
"
local assembly = RsGetCompiledAssembly "DisableWindowsGhosting" source #("System.dll") &gRsDisableGhostingAssembly forceRecompile:forceRecompile
if (assembly != undefined) do
(
assembly.DisableProcessWindowsGhosting()
)
)
------------------------------------------------------------------------------------------------------------
-- RS_CustomDataGrid
-- Generates a double-buffered DataGridView object-type,
-- with fake cells drawn in empty area at bottom of list
------------------------------------------------------------------------------------------------------------
global gRsCustomDataGridRecompile = undefined
global gRsCustomDataGridAssembly = undefined
fn RS_CustomDataGrid forceRecompile:false =
(
local source = "
using System;
using System.Windows.Forms;
using System.Drawing;
class RsCustomDataGridView: DataGridView
{
int hScrollNow = 0;
// Allows numbers and non-numbers to be sorted together:
private void customSortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
if ((e.CellValue1 == null) && (e.CellValue2 == null))
{
e.SortResult = 0;
}
else if (e.CellValue1 == null)
{
e.SortResult = -1;
}
else if (e.CellValue2 == null)
{
e.SortResult = 1;
}
else
{
string aString = String.Empty, bString = String.Empty;
bool aIsString = false, bIsString = false;
if ((e.CellValue1.GetType()) == typeof(String))
{
aString = e.CellValue1.ToString();
aIsString = true;
}
if ((e.CellValue2.GetType()) == typeof(String))
{
bString = e.CellValue2.ToString();
bIsString = true;
}
if (!aIsString && !bIsString)
{
e.SortResult = (System.Convert.ToDouble(e.CellValue1)).CompareTo(System.Convert.ToDouble(e.CellValue2));
}
else
{
if (!aIsString)
{
aString = String.Empty;
}
if (!bIsString)
{
bString = String.Empty;
}
e.SortResult = aString.CompareTo(bString);
}
}
e.Handled = true;
}
public RsCustomDataGridView()
{
DoubleBuffered = true;
RowHeadersVisible = false;
RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
SortCompare += customSortCompare;
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
DataGridView.HitTestInfo hitTestInfo = this.HitTest(e.X, e.Y);
if (hitTestInfo.Type == DataGridViewHitTestType.ColumnHeader)
{
this.DoubleBuffered = false;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (!this.DoubleBuffered)
{
this.DoubleBuffered = true;
}
}
// Draw empty rows at bottom of list, instead of grey box:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Invalidate view if it's been scrolled horizontally:
foreach (Control control in this.Controls)
{
if (control is HScrollBar)
{
HScrollBar hScroll = (HScrollBar)control;
if (hScroll.Visible)
{
if (hScrollNow != hScroll.Value)
{
hScrollNow = hScroll.Value;
this.Invalidate();
}
}
}
}
int rowHeight = this.RowTemplate.Height;
int columnHeaderHeight = ColumnHeadersVisible ? ColumnHeadersHeight : 0;
int h = columnHeaderHeight + this.Rows.GetRowsHeight(DataGridViewElementStates.None) ;
int imgWidth = this.Width - 2;
Rectangle rFrame = new Rectangle(0, 0, imgWidth, rowHeight);
Rectangle rFill = new Rectangle(1, 1, imgWidth - 2, rowHeight);
Pen pen = new Pen(this.GridColor, 1);
Bitmap rowImg = new Bitmap(imgWidth, rowHeight);
Graphics g = Graphics.FromImage(rowImg);
g.DrawRectangle(pen, rFrame);
g.FillRectangle(new SolidBrush(this.DefaultCellStyle.BackColor), rFill);
Bitmap rowImgAAlternative = rowImg.Clone() as Bitmap;
Graphics g2 = Graphics.FromImage(rowImgAAlternative);
rFill.X -= 1;
g2.FillRectangle(new SolidBrush(this.AlternatingRowsDefaultCellStyle.BackColor), rFill);
DataGridViewColumnCollection cols = this.Columns;
DataGridViewColumn thisCol = cols.GetFirstColumn(DataGridViewElementStates.None);
int w = -hScrollNow;
for (int j = 0; j < this.ColumnCount; j++)
{
g.DrawLine(pen, new Point(w, 0), new Point(w, rowHeight));
g2.DrawLine(pen, new Point(w, 0), new Point(w, rowHeight));
if (j != 0)
{
thisCol = cols.GetNextColumn(thisCol,DataGridViewElementStates.Visible,DataGridViewElementStates.None);
}
w += thisCol.Width;
}
int loop = (this.Height - h) / rowHeight;
for (int j = 0; j < loop + 1; j++)
{
int index = this.RowCount + j;
if (index % 2 == 0)
{
e.Graphics.DrawImage(rowImg, 1, h + j * rowHeight);
}
else
{
e.Graphics.DrawImage(rowImgAAlternative, 1, h + j * rowHeight);
}
}
// Redraw outer black line:
Pen outerPen = new Pen(this.ForeColor, 1);
Rectangle outerBox = this.DisplayRectangle;
outerBox.Width -= 1;
outerBox.Height -= 1;
e.Graphics.DrawRectangle(outerPen, outerBox);
}
}
"
-- Force recompile if class is undefined for no particular reason:
if (dotNetClass "RsCustomDataGridView") == undefined do
(
forceRecompile = true
)
-- STOOPID WORK-AROUND, PART 1 --
-- For some reason, this custom control works only once after first compiling, but works an unlimited number of times after recompiling:
case gRsCustomDataGridRecompile of
(
undefined:
(
gRsCustomDataGridRecompile = true
)
true:
(
gRsCustomDataGridRecompile = false
forceRecompile = true
)
)
RsGetCompiledAssembly "RsCustomDataGridView" source #("System.dll", "System.Windows.Forms.dll", "System.Drawing.dll") &gRsCustomDataGridAssembly forceRecompile:forceRecompile
-- STOOPID WORK-AROUND, PART 2 --
-- For the first run of this function, generate a control with this assembly and then re-run the function:
if gRsCustomDataGridRecompile do
(
rollout tempDataGridRoll ""
(
dotNetControl tempCtrl "RsCustomDataGridView"
on tempDataGridRoll open do
(
destroyDialog tempDataGridRoll
)
)
createDialog tempDataGridRoll pos:[-100,-100]
RS_CustomDataGrid()
)
)
------------------------------------------------------------------------------------------------------------
-- RS_CustomDataGrid
-- Generates a double-buffered DataGridView object-type,
-- with fake cells drawn in empty area at bottom of list
------------------------------------------------------------------------------------------------------------
global gRsGroupBoxAssembly = undefined
fn RsGroupBox forceRecompile:false =
(
local source = "
using System;
using System.Windows.Forms;
using System.Drawing;
class RsGroupBox: Panel
{
string _Title = \"\";
int _BoxPadding = 3;
SizeF StringSize;
public Color BoxColor;
// Set client-size to fit inside box, under title:
void SetClientSize()
{
int InPad = 2;
int PanelPad = (_BoxPadding + InPad);
int TopPad = PanelPad;
if (_Title != \"\")
{
Graphics g = CreateGraphics();
StringSize = g.MeasureString(Title, Font);
TopPad = (int)(StringSize.Height) + InPad;
}
Padding = new Padding (PanelPad, TopPad, PanelPad, PanelPad);
}
// Default box-colour is transparent version of forecolor:
void SetBoxColorFromFore()
{
BoxColor = Color.FromArgb (64,ForeColor.R,ForeColor.G,ForeColor.B);
}
protected override void OnForeColorChanged(EventArgs e)
{
SetBoxColorFromFore();
Invalidate();
}
// Init:
public RsGroupBox()
{
DoubleBuffered = true;
ResizeRedraw = true;
SetBoxColorFromFore();
SetClientSize();
}
// Auto-updates clientsize whenever title/boxpadding are changed:
public int BoxPadding
{
get { return _BoxPadding; }
set
{
_BoxPadding = value;
SetClientSize();
}
}
public string Title
{
get { return _Title; }
set
{
_Title = value;
SetClientSize();
}
}
// Draw box and label on control-paint:
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
// Draw box-line:
Point BoxPos = new Point (BoxPadding, 0);
if (StringSize.Height == 0)
{
BoxPos.Y = BoxPadding;
}
else
{
BoxPos.Y = (int)(StringSize.Height / 2);
}
// Draw box-lines:
Rectangle BoxRect = new Rectangle (BoxPos.X, BoxPos.Y, (Width - (BoxPadding * 2) - 1), (Height - BoxPos.Y - BoxPadding - 1));
Pen BoxPen = new Pen(BoxColor, 1);
g.DrawRectangle(BoxPen, BoxRect);
// Draw text:
if (Title != \"\")
{
Point StringPos = new Point ((BoxPadding + 3), 0);
Rectangle RectTextBack = new Rectangle (StringPos.X, StringPos.Y, (int)StringSize.Width, (int)StringSize.Height);
g.FillRectangle (new SolidBrush(BackColor), RectTextBack);
g.DrawString (Title, Font, (new SolidBrush(ForeColor)), StringPos.X, StringPos.Y);
}
}
}
"
-- Force recompile if class is undefined for no particular reason:
if (dotNetClass "RsGroupBox") == undefined do
(
forceRecompile = true
)
RsGetCompiledAssembly "RsGroupBox" source #("System.dll", "System.Windows.Forms.dll", "System.Drawing.dll") &gRsGroupBox forceRecompile:forceRecompile
)
------------------------------------------------------------------------------------------------------------
-- RS_intTo4Bytes
-- Outputs a large integer into an array of 4 byte-values
------------------------------------------------------------------------------------------------------------
fn RS_intTo4Bytes num =
(
local byte1 = num as integer
local byteSize = 256
local mByteSize = byteSize * byteSize
local gByteSize = mByteSize * byteSize
local byte4 = byte1 / gByteSize
byte1 -= (byte4 * gByteSize)
local byte3 = byte1 / mByteSize
byte1 -= (byte3 * mByteSize)
local byte2 = byte1 / byteSize
byte1 -= (byte2 * byteSize)
return #(byte1, byte2, byte3, byte4)
)
------------------------------------------------------------------------------------------------------------
-- RS_convertBitmapToBytes
-- Converts a Max bitmap into a byte-array in BMP format, for use with dotNet objects
------------------------------------------------------------------------------------------------------------
fn RS_convertBitmapToBytes imageBmp =
(
local imgWidth = imageBmp.width
local rowSize = imgWidth * 3
local rowPadding = for n = 1 to (mod rowSize 4) collect 0
local pixelData = #()
local getRow
for rowNum = (imageBmp.height - 1) to 0 by -1 do
(
getRow = getPixels imageBmp [0,rowNum] imgWidth
for pixel in getRow do
(
join pixelData #(pixel.r, pixel.g, pixel.b)
)
join pixelData rowPadding
)
local headerSize = 54
local bmpSize = (pixelData.count + headerSize)
local bmpArray = #(66,77)
join bmpArray (RS_intTo4Bytes bmpSize)
join bmpArray #(0,0,0,0, headerSize,0,0,0, 40,0,0,0)
join bmpArray (RS_intTo4Bytes imageBmp.width)
join bmpArray (RS_intTo4Bytes imageBmp.height)
join bmpArray #(1,0, 24,0, 0,0,0,0)
join bmpArray (RS_intTo4Bytes pixelData.count)
join bmpArray #(32,46,0,0, 32,46,0,0, 0,0,0,0, 0,0,0,0)
join bmpArray pixelData
return bmpArray
)
------------------------------------------------------------------------------------------------------------
-- RS_bitmapToImage
-- Converts a Max bitmap into a dotNet image
------------------------------------------------------------------------------------------------------------
fn RS_bitmapToImage inBmp =
(
local bmpArray = RS_convertBitmapToBytes inBmp
local memstream = dotnetobject "System.IO.MemoryStream" bmpArray
outImg = (dotnetclass "system.drawing.image").fromstream memstream
memstream.close()
return outImg
)
------------------------------------------------------------------------------------------------------------
-- Returns Max's HWND in a form compatible with dotNet Form.show function:
------------------------------------------------------------------------------------------------------------
fn RS_dotNetMaxHWND =
(
--Get the max handle pointer.
local maxHandlePointer=(Windows.GetMAXHWND())
--Convert the HWND handle of Max to a dotNet system pointer
local sysPointer = DotNetObject "System.IntPtr" maxHandlePointer
--Create a dotNet wrapper containing the maxHWND
local maxHwnd = DotNetObject "MaxCustomControls.Win32HandleWrapper" sysPointer
return maxHwnd
)
------------------------------------------------------------------------------------------------------------
-- Loads a dot net assembly, can be passed in a pattern of names to load. Returns the dot net object of the
-- last assembly to be loaded.
------------------------------------------------------------------------------------------------------------
fn RS_dotNetLoadAssembly assemblyNamePattern =
(
local assembly
for i = 1 to pluginPaths.count() do
(
local pluginPath = pluginPaths.get i
local dotNetAssemblies = getFiles (pluginPath + assemblyNamePattern)
for filename in dotNetAssemblies do
(
try
(
format " %\n" (filenameFromPath filename)
assembly = dotnet.loadAssembly filename
)
catch
(
print (getCurrentException())
Messagebox ("Failed to load assembly: " + filename + "\n\n" + (getCurrentException())) title:"Assembly Load Failure"
return false
)
)
)
assembly
)
------------------------------------------------------------------------------------------------------------
-- Loads common dot net assemblies at startup
------------------------------------------------------------------------------------------------------------
fn RS_dotNetLoadStartupAssemblies =
(
-- Load common dotNet assemblies:
format "Loading dotnet assemblies: \n"
local assemblyNames = #(
"RSG.*.dll",
"p4api.dll",
"System.Windows.Controls.DataVisualization.Toolkit.dll",
"Ionic.Zip.Partial.dll",
"Ionic.Zip.dll",
"Ionic.Zlib.dll",
"WPFToolkit.dll"
)
for namePattern in assemblyNames do
(
RS_dotNetLoadAssembly namePattern
)
)
------------------------------------------------------------------------------------------------------------
-- Print the properties/methods/events for a Dotnet-object:
------------------------------------------------------------------------------------------------------------
fn RsShowDotNetProps obj =
(
if (isKindOf obj dotNetObject) or (isKindOf obj dotNetClass) or (isKindOf obj dotNetControl) then
(
--clearListener()
format "Properties:\n"
showProperties obj
format "\nMethods:\n"
showMethods obj
format "\nEvents:\n"
showEvents obj
)
else
(
format "% is not a dotNetObject or dotNetClass\n" (obj as string)
)
)
/* USEFUL DOTNET SNIPPETS:
To print to Listener from a memory-compiled assembly, include this assembly:
"ManagedServices.dll"
Use this to print:
ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand(\"format \\\"Value: \" + Value + \"\\n\\\"\");
*/