// 本脚本只在不存在时会生成一次。组件逻辑写在当前脚本内。已存在不会再次生成覆盖 using System.IO; using UnityEngine; using FairyGUI; using NBC; using NBF.Fishing2; namespace NBF { public partial class ModelViewer : GComponent { ModelViewRenderImage _renderImage; public ModelViewRenderImage RenderImage => _renderImage; private Transform ModelRoot => _renderImage?.modelRoot; private Camera ViewCamera => _renderImage.Camera; public ModelViewerSettings ViewerSettings => _renderImage.ViewerSettings; private ItemConfig _itemConfig; private void OnInited() { _renderImage = new ModelViewRenderImage(ModelHolder.asGraph); TouchHolder.onRollOver.Set(OnFocusIn); TouchHolder.onRollOut.Set(OnFocusOut); Stage.inst.onMouseWheel.Add(OnMouseWheel); SetRotateListening(); } public override void Dispose() { Stage.inst.onMouseWheel.Remove(OnMouseWheel); _renderImage.Dispose(); base.Dispose(); } public void SetData(uint itemId) { SetData(ItemConfig.Get(itemId)); } public void SetData(ItemConfig itemConfig) { _itemConfig = itemConfig; _renderImage.LoadModel(itemConfig.GetModelPath(), ModelViewerSettings.Load(itemConfig.Id)); } public void ReSetSetting(ItemConfig itemConfig) { _renderImage.LoadModel(itemConfig.GetModelPath(), null); } public void UnloadModel() { _renderImage.UnloadModel(); } #region 用户输入操作(滑动,拖动等) private bool _focus; private float _minFOV = 10f; private float _maxFOV = 120f; private void SetRotateListening() { var dragObj = TouchHolder; var gesture1 = new SwipeGesture(dragObj); gesture1.onBegin.Set(OnSwipeBegin); gesture1.onMove.Set(OnSwipeMove); gesture1.onEnd.Set(OnSwipeEnd); } private void OnSwipeBegin(EventContext context) { var gesture = context.sender as SwipeGesture; if (gesture == null) return; if (context.inputEvent.button == 0) { _renderImage.StartRotate(gesture.position); } } private void OnSwipeMove(EventContext context) { var gesture = context.sender as SwipeGesture; if (gesture == null) return; if (context.inputEvent.button == 0) { _renderImage.UpdateRotation(gesture.position); } } private void OnSwipeEnd(EventContext context) { _renderImage.StopRotate(); } private void OnFocusIn() { _focus = true; Log.Info("focus true"); } private void OnFocusOut() { _focus = false; Log.Info("focus false"); } private void OnMouseWheel(EventContext context) { if (!_focus) return; float delta = context.inputEvent.mouseWheelDelta / Stage.devicePixelRatio; SetZoom(delta); } private void SetZoom(float delta) { ViewCamera.fieldOfView = Mathf.Clamp(ViewCamera.fieldOfView + delta, _minFOV, _maxFOV); } #endregion #region 保存png public void SaveRenderTextureToPNG() { #if UNITY_EDITOR RenderTexture rt = RenderImage.RT; if (rt == null) { Debug.LogWarning("RenderTexture 为 null,无法保存。"); return; } RenderTexture current = RenderTexture.active; RenderTexture.active = rt; Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false); tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); tex.Apply(); Texture2D resizedTex = new Texture2D(256, 256, TextureFormat.RGBA32, false); // 使用双线性滤波进行缩放 for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { // 计算在原始纹理中的对应坐标 float u = (float)x / 255f; float v = (float)y / 255f; // 获取插值后的颜色 Color color = tex.GetPixelBilinear(u, v); resizedTex.SetPixel(x, y, color); } } resizedTex.Apply(); byte[] bytes = resizedTex.EncodeToPNG(); var path = Path.Combine(Application.dataPath, $"Resources/Icons/{_itemConfig.Id}.png"); File.WriteAllBytes(path, bytes); Debug.Log($"✅ RenderTexture 已保存到: {path}"); Notices.Info($"生成:{_itemConfig.Id}"); Object.Destroy(tex); RenderTexture.active = current; #endif } #endregion } }