<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Unigine整合Myra UI Library全紀(jì)錄(1):引言,紋理與平臺

      太長不看:https://github.com/horeaper/UnigineMyraIntegration

      什么是Myra?

      這個是Myra:https://github.com/rds1983/Myra

      熟悉WPF/Avalonia/Silverlight/UWP開發(fā)的朋友肯定一眼就能看出來這個UI庫用的是什么佐料了。它當(dāng)然不是完整的WPF實(shí)現(xiàn),對于游戲開發(fā)而言也沒必要用完整的WPF,太重了。

      Myra有著和WPF非常類似的Layout系統(tǒng),運(yùn)行效率也不錯,同時還支持XML聲明(被稱為MML,Myra Markup Language),既可以實(shí)時加載XML也可以用MyraPad將這些XML轉(zhuǎn)換成C#代碼。整合進(jìn)引擎里也不麻煩。這就夠了。

      這玩意兒甚至FileDialog和ColorPickerDialog都給你做了一份,省了大事了??

      第一步:先學(xué)再用

      本文寫于Myra 1.5.9版本。

      首先建議把Github上Myra的Wiki都看一遍,大概了解一下Myra是怎么玩的。之后我建議找個空文件夾git clone https://github.com/rds1983/Myra.git,然后打開Myra\build\Myra.PlatformAgnostic.sln,你會看到幾個項(xiàng)目,其中在Samples文件夾下面有這三個示例項(xiàng)目:

      • Samples/Myra.Samples.PlatformAgnostic:用MonoGame手動整合,不使用自帶的整合方式,而是手動從接口繼承并實(shí)現(xiàn)所有接口功能。如果你要整合的目標(biāo)引擎里面有Xna的SpriteBatch類似物,那么直接照著這個例子去做就夠了。
      • Samples/Myra.Samples.Silk.NET:用Silk.NET + OpenGL整合,是最底層的整合方式。雖然窗口框架還是Silk.NET提供的,不過其負(fù)責(zé)渲染的QuadBatch.cs完全是手寫。如果你要整合的目標(biāo)引擎里面只提供了最基礎(chǔ)的Mesh渲染方式(比如Unigine),那么就要參考這個例子來做。
      • Samples/Myra.Samples.Silk.NET.TrippyGL:仍然是Silk.NET + OpenGL整合,但使用TrippyGL簡化了代碼。TrippyGL提供了一個SpriteBatch類似物,叫TextureBatcher,因此這個整合過程和手動MonoGame整合很類似。其實(shí)可以跳過不看。

      最后是Myra.PlatformAgnostic,Myra主項(xiàng)目,代碼雖然很多但整理的很有序,想看可以鉆進(jìn)去看,但目前先不走那么深。

      接下來建議去這里:https://github.com/unigine-engine/unigine-imgui-csharp-integration-sample

      這個例子是Unigine整合ImGui.NET的例子,其中ImGuiImpl.cs是整個實(shí)現(xiàn)過程。別被這看上去亂七八糟的文件嚇到,其實(shí)它內(nèi)容還是挺簡單的,只是把幾個不同的模塊全寫在了一個類里面。好孩子不要這么做哦!

      向Unigine整合新的GUI系統(tǒng),絕大部分內(nèi)容都可以參考這個ImGui.NET的實(shí)現(xiàn)方式。后文我也會多次提到這個東西。

      第二步:準(zhǔn)備工作

      Myra自帶有MonoGame、FNA和Stride的整合,同時還有PlatformAgnostic包用來應(yīng)付其他的情況。我們當(dāng)然要用這個包,給項(xiàng)目加上Myra支持很簡單,畢竟這是Unigine??:

      dotnet add package Myra.PlatformAgnostic
      

      然后在source文件夾下建個新的文件夾,就叫MyraIntegration好了。

      整合Myra到Unigine,包括整合到其他所有引擎,大概有這么幾步工作:

      1. 實(shí)現(xiàn)接口ITexture2DManager,實(shí)現(xiàn)對紋理的創(chuàng)建和屬性獲取。
      2. 實(shí)現(xiàn)接口IMyraRenderer,實(shí)現(xiàn)窗口Scissor的設(shè)置和紋理的繪制
      3. 實(shí)現(xiàn)接口IMyraPlatform,向Myra提供窗口、鍵盤、鼠標(biāo)和觸屏的信息。目前我們暫時不管觸屏。
      4. 最后,將上述實(shí)現(xiàn)提供給MyraEnvironment.Platform,再創(chuàng)建一個Myra.Graphics2D.UI.Desktop對象,將Desktop.Root設(shè)置成UI控件的實(shí)現(xiàn),最后通過Desktop.Render()渲染出結(jié)果。

      那么,接下來一個一個的處理:

      ITexture2DManager

      Unigine創(chuàng)建紋理要分兩步走,注意創(chuàng)建為RGBA8格式,Usage要加上Dynamic,并且設(shè)置為Point Filter:

      object ITexture2DManager.CreateTexture(int width, int height)
      {
      	var texture = new Texture();
      	texture.Create2D(width, height, Texture.FORMAT_RGBA8, Texture.FORMAT_USAGE_DYNAMIC | Texture.SAMPLER_FILTER_POINT);
      	return texture;
      }
      

      Myra有個功能是Smooth Font,需要將紋理Filter設(shè)置為Bilinear。這個功能并不是指定渲染的字體是否有抗鋸齒(抗鋸齒是一直啟用的),而是在UI發(fā)生縮放的時候是否對渲染出來的文字做平滑化。目前我們先不管這個。

      之后要告訴Myra紋理的尺寸,畢竟傳給Myra的是一個object而沒有其他的信息:

      Point ITexture2DManager.GetTextureSize(object obj)
      {
      	var texture = (Texture)obj;
      	return new Point(texture.GetWidth(), texture.GetHeight());
      }
      

      接下來要將圖像數(shù)據(jù)傳遞給紋理:

      void ITexture2DManager.SetTextureData(object obj, Rectangle bounds, byte[] data)
      {
      	using var image = new Image();
      	image.Create2D(bounds.Width, bounds.Height, Image.FORMAT_RGBA8, 1, false);
      	image.SetPixels(data);
      
      	var texture = (Texture)obj;
      	texture.SetImage2D(image, bounds.X, bounds.Y);
      
      	image.SetPixels((byte[])null!);
      }
      

      Unigine沒有類似OpenGL的glTexSubImage2D,不能直接往紋理上寫數(shù)據(jù),需要創(chuàng)建一個Image對象然后拷貝過去。
      創(chuàng)建的Image對象也得是RGBA8格式,和紋理保持一致。不需要Mipmap,并將clear參數(shù)設(shè)置成false,畢竟馬上就要用數(shù)據(jù)寫滿整個Image。

      后面就很好理解了,將Image傳遞給Texture進(jìn)行數(shù)據(jù)上傳。接下來這一行image.SetPixels((byte[])null!)不是C#里常見的操作:將Image的緩沖區(qū)設(shè)置為null。這一點(diǎn)和Unigine的C++底層實(shí)現(xiàn)有關(guān),它的C++底層會直接拿data的指針去用,而不進(jìn)行數(shù)據(jù)拷貝。因此在最后Image.Dispose的時候會報錯。因此這里要設(shè)置為空。

      這個古怪的設(shè)計卡了我好一段時間,直到我仔細(xì)翻閱了ImGui.NET的實(shí)現(xiàn)才搞明白。你可以在ImGuiImpl.cs的create_font_texture()函數(shù)里找到類似的東西。示例里使用了一個Blob進(jìn)行中轉(zhuǎn),因?yàn)槭纠龔腎mGui獲取的數(shù)據(jù)是RGBA32格式的,需要多一個步驟轉(zhuǎn)換成RGBA8。Myra這邊數(shù)據(jù)格式是相同的因此可以省略這一步。

      IMyraPlatform

      Renderer牽扯的東西多一些,先來搞Platform。

      Myra需要知道渲染窗口的大小,也就是Unigine的ClientRenderSize:

      Point IMyraPlatform.ViewSize
      {
      	get {
      		var clientRenderSize = WindowManager.MainWindow.ClientRenderSize;
      		return new Point(clientRenderSize.x, clientRenderSize.y);
      	}
      }
      

      之后實(shí)現(xiàn)向Myra提供鼠標(biāo)信息的接口:

      int mouseWheelValue;
      
      MouseInfo IMyraPlatform.GetMouseInfo()
      {
      	var position = Input.MousePosition - WindowManager.MainWindow.ClientPosition;
      	mouseWheelValue += Input.MouseWheel;
      	return new MouseInfo {
      		IsLeftButtonDown = Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.LEFT),
      		IsRightButtonDown = Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.RIGHT),
      		IsMiddleButtonDown = Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.MIDDLE),
      		Position = new Point(position.x, position.y),
      		Wheel = mouseWheelValue,
      	};
      }
      

      有兩點(diǎn)要注意。第一點(diǎn)是這里要使用Input.IsMouseButtonPressed而不是Input.IsMouseButtonDown,后者返回的是當(dāng)前幀內(nèi)鼠標(biāo)按鍵是否有被按下過。另一點(diǎn)是鼠標(biāo)滾輪數(shù)據(jù),Myra需要的是累計后的絕對值(Xna的處理方式)而不是常見的相對值,因此這里定義了一個mouseWheelValue變量將歷史數(shù)據(jù)累加起來再傳遞給Myra。

      接下來需要向Myra提供鍵盤信息。由于Myra的Keys值和Unigine的不一樣(Myra用的是Xna的值,也就是Windows平臺的值,Unigine使用了一套自己的東西),因此需要創(chuàng)建一個映射表:

      readonly Keys[] UnigineToMyraKeyMap = new Keys[(int)Input.KEY.NUM_KEYS];
      
      void GenerateMyraKeyMap()
      {
      	UnigineToMyraKeyMap[(int)Input.KEY.ESC] = Keys.Escape;
      	UnigineToMyraKeyMap[(int)Input.KEY.F1] = Keys.F1;
      	UnigineToMyraKeyMap[(int)Input.KEY.F2] = Keys.F2;
      	UnigineToMyraKeyMap[(int)Input.KEY.F3] = Keys.F3;
      	UnigineToMyraKeyMap[(int)Input.KEY.F4] = Keys.F4;
      	UnigineToMyraKeyMap[(int)Input.KEY.F5] = Keys.F5;
      	UnigineToMyraKeyMap[(int)Input.KEY.F6] = Keys.F6;
      	UnigineToMyraKeyMap[(int)Input.KEY.F7] = Keys.F7;
      	UnigineToMyraKeyMap[(int)Input.KEY.F8] = Keys.F8;
      	UnigineToMyraKeyMap[(int)Input.KEY.F9] = Keys.F9;
      	UnigineToMyraKeyMap[(int)Input.KEY.F10] = Keys.F10;
      	UnigineToMyraKeyMap[(int)Input.KEY.F11] = Keys.F11;
      	UnigineToMyraKeyMap[(int)Input.KEY.F12] = Keys.F12;
      	UnigineToMyraKeyMap[(int)Input.KEY.PRINTSCREEN] = Keys.PrintScreen;
      	UnigineToMyraKeyMap[(int)Input.KEY.SCROLL_LOCK] = Keys.Scroll;
      	UnigineToMyraKeyMap[(int)Input.KEY.PAUSE] = Keys.Pause;
      	UnigineToMyraKeyMap[(int)Input.KEY.BACK_QUOTE] = Keys.OemTilde;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_1] = Keys.D1;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_2] = Keys.D2;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_3] = Keys.D3;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_4] = Keys.D4;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_5] = Keys.D5;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_6] = Keys.D6;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_7] = Keys.D7;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_8] = Keys.D8;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_9] = Keys.D9;
      	UnigineToMyraKeyMap[(int)Input.KEY.DIGIT_0] = Keys.D0;
      	UnigineToMyraKeyMap[(int)Input.KEY.MINUS] = Keys.OemMinus;
      	UnigineToMyraKeyMap[(int)Input.KEY.EQUALS] = Keys.OemPlus;
      	UnigineToMyraKeyMap[(int)Input.KEY.BACKSPACE] = Keys.Back;
      	UnigineToMyraKeyMap[(int)Input.KEY.TAB] = Keys.Tab;
      	UnigineToMyraKeyMap[(int)Input.KEY.Q] = Keys.Q;
      	UnigineToMyraKeyMap[(int)Input.KEY.W] = Keys.W;
      	UnigineToMyraKeyMap[(int)Input.KEY.E] = Keys.E;
      	UnigineToMyraKeyMap[(int)Input.KEY.R] = Keys.R;
      	UnigineToMyraKeyMap[(int)Input.KEY.T] = Keys.T;
      	UnigineToMyraKeyMap[(int)Input.KEY.Y] = Keys.Y;
      	UnigineToMyraKeyMap[(int)Input.KEY.U] = Keys.U;
      	UnigineToMyraKeyMap[(int)Input.KEY.I] = Keys.I;
      	UnigineToMyraKeyMap[(int)Input.KEY.O] = Keys.O;
      	UnigineToMyraKeyMap[(int)Input.KEY.P] = Keys.P;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT_BRACKET] = Keys.OemOpenBrackets;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT_BRACKET] = Keys.OemCloseBrackets;
      	UnigineToMyraKeyMap[(int)Input.KEY.ENTER] = Keys.Enter;
      	UnigineToMyraKeyMap[(int)Input.KEY.CAPS_LOCK] = Keys.CapsLock;
      	UnigineToMyraKeyMap[(int)Input.KEY.A] = Keys.A;
      	UnigineToMyraKeyMap[(int)Input.KEY.S] = Keys.S;
      	UnigineToMyraKeyMap[(int)Input.KEY.D] = Keys.D;
      	UnigineToMyraKeyMap[(int)Input.KEY.F] = Keys.F;
      	UnigineToMyraKeyMap[(int)Input.KEY.G] = Keys.G;
      	UnigineToMyraKeyMap[(int)Input.KEY.H] = Keys.H;
      	UnigineToMyraKeyMap[(int)Input.KEY.J] = Keys.J;
      	UnigineToMyraKeyMap[(int)Input.KEY.K] = Keys.K;
      	UnigineToMyraKeyMap[(int)Input.KEY.L] = Keys.L;
      	UnigineToMyraKeyMap[(int)Input.KEY.SEMICOLON] = Keys.OemSemicolon;
      	UnigineToMyraKeyMap[(int)Input.KEY.QUOTE] = Keys.OemQuotes;
      	UnigineToMyraKeyMap[(int)Input.KEY.BACK_SLASH] = Keys.OemBackslash;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT_SHIFT] = Keys.LeftShift;
      	UnigineToMyraKeyMap[(int)Input.KEY.LESS] = Keys.Apps;
      	UnigineToMyraKeyMap[(int)Input.KEY.Z] = Keys.Z;
      	UnigineToMyraKeyMap[(int)Input.KEY.X] = Keys.X;
      	UnigineToMyraKeyMap[(int)Input.KEY.C] = Keys.C;
      	UnigineToMyraKeyMap[(int)Input.KEY.V] = Keys.V;
      	UnigineToMyraKeyMap[(int)Input.KEY.B] = Keys.B;
      	UnigineToMyraKeyMap[(int)Input.KEY.N] = Keys.N;
      	UnigineToMyraKeyMap[(int)Input.KEY.M] = Keys.M;
      	UnigineToMyraKeyMap[(int)Input.KEY.COMMA] = Keys.OemComma;
      	UnigineToMyraKeyMap[(int)Input.KEY.DOT] = Keys.OemPeriod;
      	UnigineToMyraKeyMap[(int)Input.KEY.SLASH] = Keys.OemQuestion;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT_SHIFT] = Keys.RightShift;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT_CTRL] = Keys.LeftControl;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT_CMD] = Keys.LeftWindows;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT_ALT] = Keys.LeftAlt;
      	UnigineToMyraKeyMap[(int)Input.KEY.SPACE] = Keys.Space;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT_ALT] = Keys.RightAlt;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT_CMD] = Keys.RightWindows;
      	UnigineToMyraKeyMap[(int)Input.KEY.MENU] = Keys.None;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT_CTRL] = Keys.RightControl;
      	UnigineToMyraKeyMap[(int)Input.KEY.INSERT] = Keys.Insert;
      	UnigineToMyraKeyMap[(int)Input.KEY.DELETE] = Keys.Delete;
      	UnigineToMyraKeyMap[(int)Input.KEY.HOME] = Keys.Home;
      	UnigineToMyraKeyMap[(int)Input.KEY.END] = Keys.End;
      	UnigineToMyraKeyMap[(int)Input.KEY.PGUP] = Keys.PageUp;
      	UnigineToMyraKeyMap[(int)Input.KEY.PGDOWN] = Keys.PageDown;
      	UnigineToMyraKeyMap[(int)Input.KEY.UP] = Keys.Up;
      	UnigineToMyraKeyMap[(int)Input.KEY.LEFT] = Keys.Left;
      	UnigineToMyraKeyMap[(int)Input.KEY.DOWN] = Keys.Down;
      	UnigineToMyraKeyMap[(int)Input.KEY.RIGHT] = Keys.Right;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUM_LOCK] = Keys.NumLock;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIVIDE] = Keys.Divide;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_MULTIPLY] = Keys.Multiply;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_MINUS] = Keys.Subtract;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_7] = Keys.NumPad7;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_8] = Keys.NumPad8;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_9] = Keys.NumPad9;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_PLUS] = Keys.Add;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_4] = Keys.NumPad4;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_5] = Keys.NumPad5;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_6] = Keys.NumPad6;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_1] = Keys.NumPad1;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_2] = Keys.NumPad2;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_3] = Keys.NumPad3;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_ENTER] = Keys.Enter;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DIGIT_0] = Keys.NumPad0;
      	UnigineToMyraKeyMap[(int)Input.KEY.NUMPAD_DOT] = Keys.Decimal;
      }
      

      有了這個映射表之后,向Myra提供鍵盤信息就很簡單了:

      void IMyraPlatform.SetKeysDown(bool[] keys)
      {
      	for (int key = 0; key < (int)Input.KEY.NUM_KEYS; ++key) {
      		var myraKey = UnigineToMyraKeyMap[key];
      		keys[(int)myraKey] = Input.IsKeyDown((Input.KEY)key);
      	}
      }
      

      和鼠標(biāo)那邊不同,長按一個鍵盤按鍵的時候,Input.IsKeyDown會多次觸發(fā),因此可以實(shí)現(xiàn)長按按鍵連續(xù)輸入的效果。

      剩下的兩個:

      void IMyraPlatform.SetMouseCursorType(MouseCursorType mouseCursorType)
      {
      	//TODO: Use game's custom cursor with Input.SetMouseCursorCustom()
      }
      
      TouchCollection IMyraPlatform.GetTouchState()
      {
      	return TouchCollection.Empty;
      }
      

      SetMouseCursorType這里,根據(jù)傳進(jìn)來的MouseCursorType,用Input.SetMouseCursorCustom()設(shè)置成游戲自定義的光標(biāo)即可。目前先略過。

      GetTouchState這里,可以先忽略。Unigine是有觸控處理的API的,就在Input里面,想實(shí)現(xiàn)也可以實(shí)現(xiàn),不過目前Unigine不支持移動平臺,忽略掉也不會有太大的問題。

      posted @ 2025-09-25 14:11  horeaper  閱讀(147)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 夜夜高潮次次欢爽av女| 亚洲av中文乱码一区二| 爆乳女仆高潮在线观看| 亚洲欧洲日韩国内高清| 牲欲强的熟妇农村老妇女视频| 狠狠色噜噜狠狠狠狠777米奇| 特级毛片a片久久久久久| 久久综合伊人77777| 成人午夜电影福利免费| 成人国产精品一区二区网站公司| 狠狠色综合久久丁香婷婷| 国产稚嫩高中生呻吟激情在线视频| 国产成人欧美一区二区三区| 九九热久久只有精品2| 蜜臀精品视频一区二区三区| 亚洲精品国产一区二区三区在线观看 | 中文字幕久区久久中文字幕| 无码人妻丝袜在线视频| ww污污污网站在线看com| 亚洲精品一二三四区| 亚洲av第二区国产精品| 久久精品国产91精品亚洲| 亚洲av午夜成人片| 丝袜无码一区二区三区| 人妻丝袜AV中文系列先锋影音| 熟妇人妻激情偷爽文| 欧美国产日韩在线三区| 日韩不卡一区二区在线观看| 51妺嘿嘿午夜福利| 亚洲伊人久久综合成人| 亚洲av日韩在线资源| 国产成人女人在线观看| 女同性恋一区二区三区视频| 熟女在线视频一区二区三区| 欧美精品亚洲精品日韩专| 亚洲精品香蕉一区二区| av中文无码乱人伦在线观看| 麻豆国产传媒精品视频| 又污又爽又黄的网站| 无码av天天av天天爽| 蜜芽久久人人超碰爱香蕉|