icon预览和自动生成

This commit is contained in:
Bob.Song
2025-10-28 17:46:08 +08:00
parent af4dbc5cde
commit 7b8c6d5cec
204 changed files with 8454 additions and 174 deletions

View File

@@ -11,10 +11,11 @@ namespace NBF
[Serializable]
public class ModelViewRenderImage
{
private ModelViewerSettings _viewerSettings;
public Transform modelRoot { get; private set; }
public Camera Camera => _camera;
public RenderTexture RT => _renderTexture;
public ModelViewerSettings ViewerSettings { get; private set; }
Camera _camera;
Image _image;
Transform _root;
@@ -47,7 +48,7 @@ namespace NBF
Object prefab = Resources.Load("RenderTexture/RenderImageCamera");
GameObject go = (GameObject)Object.Instantiate(prefab, _root, false);
_camera = go.GetComponent<Camera>();
_camera.transform.position = Vector3.zero;
_camera.cullingMask = 1 << RENDER_LAYER;
@@ -65,7 +66,7 @@ namespace NBF
_image.onRemovedFromStage.Add(OnRemoveFromStage);
_viewerSettings = new ModelViewerSettings();
// _viewerSettings = new ModelViewerSettings();
if (_image.stage != null)
OnAddedToStage();
@@ -73,11 +74,13 @@ namespace NBF
_camera.gameObject.SetActive(false);
}
public void LoadModel(string model)
public void LoadModel(string model, ModelViewerSettings settings)
{
this.UnloadModel();
ViewerSettings = settings;
Object prefab = Resources.Load(model);
if(prefab == null) return;
GameObject go = ((GameObject)Object.Instantiate(prefab));
var joint = go.GetComponent<Joint>();
if (joint != null)
@@ -90,7 +93,12 @@ namespace NBF
_model.localPosition = Vector3.zero;
_model.localScale = Vector3.one;
_model.localEulerAngles = Vector3.zero;
ModelViewerUtils.InitSetting(go, _viewerSettings);
if (ViewerSettings == null)
{
ViewerSettings = new ModelViewerSettings();
ModelViewerUtils.InitSetting(go, ViewerSettings);
}
Review();
}
@@ -109,22 +117,22 @@ namespace NBF
public void Review()
{
_model.position = _viewerSettings.objectPosition;
_model.localScale = _viewerSettings.objectScale;
_model.eulerAngles = _viewerSettings.objectRotation;
_model.position = ViewerSettings.objectPosition;
_model.localScale = ViewerSettings.objectScale;
_model.eulerAngles = ViewerSettings.objectRotation;
_camera.clearFlags = CameraClearFlags.Nothing;
_camera.backgroundColor = new Color(0, 0, 0, 0); // 完全透明
_camera.transform.position = _viewerSettings.cameraPosition;
_camera.transform.LookAt(_viewerSettings.cameraTarget);
_camera.orthographic = _viewerSettings.cameraOrtho;
_camera.orthographicSize = _viewerSettings.cameraSize;
_camera.orthographicSize /= _viewerSettings.camerasScaleFactor;
_camera.transform.position = ViewerSettings.cameraPosition;
_camera.transform.LookAt(ViewerSettings.cameraTarget);
_camera.orthographic = ViewerSettings.cameraOrtho;
_camera.orthographicSize = ViewerSettings.cameraSize;
_camera.orthographicSize /= ViewerSettings.camerasScaleFactor;
_camera.fieldOfView = _viewerSettings.cameraFov;
_camera.fieldOfView = ViewerSettings.cameraFov;
float fov = 2 * Mathf.Rad2Deg * Mathf.Atan2(
Mathf.Tan(_camera.fieldOfView * Mathf.Deg2Rad / 2), _viewerSettings.camerasScaleFactor
Mathf.Tan(_camera.fieldOfView * Mathf.Deg2Rad / 2), ViewerSettings.camerasScaleFactor
);
if (fov < 0)
fov += 180;
@@ -135,13 +143,6 @@ namespace NBF
_camera.depthTextureMode = DepthTextureMode.Depth;
_camera.clearFlags = CameraClearFlags.Color;
_camera.GetUniversalAdditionalCameraData().renderPostProcessing = false; //URP only
// var urpCamData = _camera.GetUniversalAdditionalCameraData();
// urpCamData.renderPostProcessing = false;
// urpCamData.requiresColorOption = CameraOverrideOption.On;
// urpCamData.requiresDepthOption = CameraOverrideOption.Off;
// urpCamData.requiresColorTexture = false;
// urpCamData.SetRenderer(1); // 关键步骤指定“透明输出”的Renderer
}
public void Dispose()
@@ -160,7 +161,7 @@ namespace NBF
if (_renderTexture != null)
return;
_renderTexture = new RenderTexture(1024, 1024, 24, RenderTextureFormat.ARGB32)
_renderTexture = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32)
{
antiAliasing = 1,
filterMode = FilterMode.Bilinear,

View File

@@ -1,5 +1,6 @@
// 本脚本只在不存在时会生成一次。组件逻辑写在当前脚本内。已存在不会再次生成覆盖
using System.IO;
using UnityEngine;
using FairyGUI;
using NBC;
@@ -11,9 +12,14 @@ namespace NBF
{
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);
@@ -38,16 +44,22 @@ namespace NBF
public void SetData(ItemConfig itemConfig)
{
_renderImage.LoadModel("gfx/" + itemConfig.Model);
_itemConfig = itemConfig;
_renderImage.LoadModel(itemConfig.GetModelPath(), ModelViewerSettings.Load(itemConfig.Id));
}
public void ReSetSetting(ItemConfig itemConfig)
{
_renderImage.LoadModel(itemConfig.GetModelPath(), null);
}
#region ()
private bool _focus;
private float _minFOV = 10f;
private float _maxFOV = 120f;
private void SetRotateListening()
{
var dragObj = TouchHolder;
@@ -104,10 +116,63 @@ namespace NBF
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
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using Newtonsoft.Json;
using UnityEngine;
using Color = UnityEngine.Color;
@@ -9,17 +10,12 @@ namespace NBF
[Serializable]
public class ModelViewerSettings
{
//Object Settings
//物体设置
public Vector3 objectPosition;
public Vector3 objectRotation;
public Vector3 objectScale;
//Hierarchy Settings
[NonSerialized] public Dictionary<string, bool> subObjectEnables;
public List<string> soeStrings;
public List<bool> soeBools;
//Camera Settings
//摄像机设置
public Vector3 cameraPosition;
public Vector3 cameraTarget;
public bool autoPosition;
@@ -30,47 +26,42 @@ namespace NBF
public float camerasScaleFactor;
public float perspLastScale;
//Lighting Settings
//灯光设置
public Color lightColour;
public Vector3 lightDir;
public float lightIntensity;
public Color ambientLightColour;
//Animation Settings
public AnimationClip animationClip;
public float animationOffset;
public string animationPath;
//Post-Processing Settings
public List<Material> postProcessingMaterials;
public Dictionary<Material, String> materialDisplayNames;
public Dictionary<Material, bool> materialToggles;
public enum FixEdgesModes
public static ModelViewerSettings Load(uint id)
{
None,
Regular,
WithDepthTexture
};
public FixEdgesModes fixEdgesMode;
public FilterMode filterMode;
var configAsset = Resources.Load<TextAsset>($"config/Viewer/{id}");
if (configAsset != null)
{
return JsonConvert.DeserializeObject<ModelViewerSettings>(configAsset.text);
}
return null;
}
public ModelViewerSettings()
{
//Do nothing
//---Initialise Icon---//
//Object Settings
SetDefValues();
}
public ModelViewerSettings(Shader objRenderShader, string rapidIconRootFolder, GameObject rootObject)
{
SetDefValues();
}
private void SetDefValues()
{
objectPosition = Vector3.zero;
objectRotation = Vector3.zero;
objectScale = Vector3.one;
autoPosition = true;
//Hierarchy Settings
subObjectEnables = new Dictionary<string, bool>();
//Camera Settings
cameraPosition = new Vector3(1, Mathf.Sqrt(2), 1);
perspLastScale = 1;
cameraOrtho = false;
@@ -80,69 +71,10 @@ namespace NBF
cameraTarget = Vector3.zero;
autoScale = true;
//Lighting Settings
ambientLightColour = Color.gray;
lightColour = Color.white;
lightDir = new Vector3(50, -30, 0);
lightIntensity = 1;
//Post-Processing Settings
postProcessingMaterials = new List<Material>();
materialDisplayNames = new Dictionary<Material, string>();
materialToggles = new Dictionary<Material, bool>();
filterMode = FilterMode.Point;
fixEdgesMode = FixEdgesModes.Regular;
}
public ModelViewerSettings(Shader objRenderShader, string rapidIconRootFolder, GameObject rootObject)
{
//---Initialise Icon---//
//Object Settings
objectPosition = Vector3.zero;
objectRotation = Vector3.zero;
objectScale = Vector3.one;
autoPosition = true;
//Hierarchy Settings
subObjectEnables = new Dictionary<string, bool>();
//Camera Settings
cameraPosition = new Vector3(1, Mathf.Sqrt(2), 1);
perspLastScale = 1;
cameraOrtho = true;
cameraFov = 60;
cameraSize = 5;
camerasScaleFactor = 1;
cameraTarget = Vector3.zero;
autoScale = true;
//Lighting Settings
ambientLightColour = Color.gray;
lightColour = Color.white;
lightDir = new Vector3(50, -30, 0);
lightIntensity = 1;
//Post-Processing Settings
postProcessingMaterials = new List<Material>();
materialDisplayNames = new Dictionary<Material, string>();
materialToggles = new Dictionary<Material, bool>();
filterMode = FilterMode.Point;
fixEdgesMode = FixEdgesModes.Regular;
// Material defaultRender = new Material(objRenderShader);
// postProcessingMaterials.Add(defaultRender);
// materialDisplayNames.Add(defaultRender, "Object Render");
// materialToggles.Add(defaultRender, true);
}
void SetSubObjectEnables(GameObject obj, int childIdx, string lastPath)
{
string path = lastPath + "/" + childIdx;
subObjectEnables.Add(path, true);
for (int i = 0; i < obj.transform.childCount; i++)
{
SetSubObjectEnables(obj.transform.GetChild(i).gameObject, i, path);
}
}
}
}

View File

@@ -0,0 +1,42 @@
/**本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/
using FairyGUI;
using FairyGUI.Utils;
using NBC;
using System.Collections.Generic;
namespace NBF
{
/// <summary> </summary>
public partial class PreviewDetailsPanel
{
public GObject this[string aKey] => ContentPane.GetChild(aKey);
public override string UIPackName => "Tools";
public override string UIResName => "PreviewDetailsPanel";
[AutoFind(Name = "title")]
public GComponent title;
[AutoFind(Name = "modelBack")]
public GImage modelBack;
[AutoFind(Name = "Model")]
public ModelViewer Model;
[AutoFind(Name = "Quality")]
public GImage Quality;
[AutoFind(Name = "Basic")]
public ItemBasicInfoTag Basic;
[AutoFind(Name = "BtnSaveIcon")]
public GButton BtnSaveIcon;
[AutoFind(Name = "BtnReSet")]
public GButton BtnReSet;
[AutoFind(Name = "BtnSaveSetting")]
public GButton BtnSaveSetting;
public override string[] GetDependPackages(){ return new string[] {"Common","Main"}; }
public static void Show(object param = null){ App.UI.OpenUI<PreviewDetailsPanel>(param); }
public static void Hide(){ App.UI.HideUI<PreviewDetailsPanel>(); }
public static void Del(){ App.UI.DestroyUI<PreviewDetailsPanel>(); }
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 156ad87133aee5c4a8436e94407c37c5

View File

@@ -0,0 +1,82 @@
// 本脚本只在不存在时会生成一次。已存在不会再次生成覆盖
using System.IO;
using FairyGUI;
using UnityEngine;
using NBC;
using NBC.Asset;
using Newtonsoft.Json;
using UIPanel = NBC.UIPanel;
namespace NBF
{
public partial class PreviewDetailsPanel : UIPanel
{
public ItemInfo ItemInfo;
protected override void OnInit()
{
this.AutoAddClick(OnBtnClick);
}
protected override void OnShow()
{
ItemInfo = GetData() as ItemInfo;
Quality.SetQuality(ItemInfo.Config.Quality);
Basic.SetInfo(ItemInfo);
// var model = PrefabsHelper.CreatePrefab(ItemInfo.Config.Model);
Model.SetData(ItemInfo.Config);
// Model.SetBackground(Back);
Game.Input.OnUICanceled += OnUICanceled;
}
private void OnUICanceled(string action)
{
if (!IsTop) return;
if (action == InputDef.UI.SubPrev)
{
}
else if (action == InputDef.UI.SubNext)
{
}
else if (action == InputDef.UI.Up)
{
}
else if (action == InputDef.UI.Down)
{
}
}
private void OnBtnClick(GComponent btn)
{
if (btn == BtnSaveIcon)
{
Model.SaveRenderTextureToPNG();
#if UNITY_EDITOR
UnityEditor.AssetDatabase.Refresh();
#endif
}
else if (btn == BtnSaveSetting)
{
var setting = Model.ViewerSettings;
var json = JsonUtility.ToJson(setting); //JsonConvert.SerializeObject(setting);
//Assets/Resources/config/Viewer
var savePath = Path.Combine(Application.dataPath, $"Resources/config/Viewer/{ItemInfo.ConfigId}.json");
File.WriteAllText(savePath, json);
#if UNITY_EDITOR
UnityEditor.AssetDatabase.Refresh();
#endif
}
else if (btn == BtnReSet)
{
Model.ReSetSetting(ItemInfo.Config);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8eefc162282655e4aac6215d90c38c95

View File

@@ -14,9 +14,15 @@ namespace NBF
public override string UIPackName => "Tools";
public override string UIResName => "PreviewPanel";
[AutoFind(Name = "Model")]
public ModelViewer Model;
public override string[] GetDependPackages(){ return new string[] {"Common"}; }
[AutoFind(Name = "ItemList")]
public CommonItemList ItemList;
[AutoFind(Name = "ItemModal")]
public BagItem ItemModal;
[AutoFind(Name = "BtnGenAllIcon")]
public GButton BtnGenAllIcon;
[AutoFind(Name = "GenModel")]
public ModelViewer GenModel;
public override string[] GetDependPackages(){ return new string[] {"Common","Main"}; }
public static void Show(object param = null){ App.UI.OpenUI<PreviewPanel>(param); }

View File

@@ -1,20 +1,163 @@
// 本脚本只在不存在时会生成一次。已存在不会再次生成覆盖
using System.Collections;
using System.Collections.Generic;
using FairyGUI;
using UnityEngine;
using NBC;
using NBF.Fishing2;
using NBF.Utils;
using UIPanel = NBC.UIPanel;
namespace NBF
{
public partial class PreviewPanel : UIPanel
{
public GameObject Instance { get; private set; }
private List<ItemInfo> _itemInfos = new List<ItemInfo>();
public GameObject LoadModel(GameObject prefab)
protected override void OnInit()
{
Instance = Object.Instantiate(prefab);
Debug.LogError($"预制体:{prefab.name} 实例={Instance}");
// Model.SetModel(Instance);
return Instance;
this.AutoAddClick(OnBtnClick);
}
protected override void OnShow()
{
ItemList.List.OnClickItem += OnClickItem;
Game.Input.OnUICanceled += OnUICanceled;
List<TabItemData> tabItemList = new List<TabItemData>();
var dic = GetItemsByType();
foreach (var (type, list) in dic)
{
TabItemData tabItem = new TabItemData
{
Key = type.ToString()
};
tabItem.Items.AddRange(list);
tabItemList.Add(tabItem);
}
ItemList.SetPanel(this);
ItemList.SetData(tabItemList, true, true);
}
private void OnBtnClick(GComponent btn)
{
if (btn == BtnGenAllIcon)
{
AutoGenIcon();
}
}
private void OnUICanceled(string action)
{
if (!IsTop) return;
if (action == InputDef.UI.SubPrev)
{
}
else if (action == InputDef.UI.SubNext)
{
}
else if (action == InputDef.UI.Up)
{
}
else if (action == InputDef.UI.Down)
{
}
}
private void OnClickItem(object item)
{
if (item is not BagItem bagItem) return;
PreviewDetailsPanel.Show(bagItem.ItemInfo);
}
#region
public Dictionary<ItemType, List<ItemInfo>> GetItemsByType()
{
// List<ItemInfo> Items = new List<ItemInfo>();
_itemInfos.Clear();
var configs = ItemConfig.GetList();
foreach (var itemConfig in configs)
{
ItemInfo itemInfo = new ItemInfo
{
ConfigId = itemConfig.Id,
Count = 1
};
_itemInfos.Add(itemInfo);
}
var dic = new Dictionary<ItemType, List<ItemInfo>>();
foreach (var item in _itemInfos)
{
var type = item.ConfigId.GetItemType();
if (!dic.ContainsKey(type))
{
dic.Add(type, new List<ItemInfo>());
}
dic[type].Add(item);
}
foreach (var (key, list) in dic)
{
list.Sort((x, y) => (int)(y.Config.Quality - x.Config.Quality));
}
return dic;
}
#endregion
#region icon
private int _index = -1;
private void AutoGenIcon()
{
// Timer.ClearAll(this);
// Timer.Loop(2f, this, NextIcon);
Game.Instance.StartCoroutine(NextIcon());
}
private IEnumerator NextIcon()
{
foreach (var item in _itemInfos)
{
GenModel.visible = true;
GenModel.SetData(item.Config);
yield return new WaitForSeconds(1f);
GenModel.SaveRenderTextureToPNG();
yield return new WaitForSeconds(1f);
}
#if UNITY_EDITOR
GenModel.visible = false;
UnityEditor.AssetDatabase.Refresh();
Timer.ClearAll(this);
Log.Info("全部完成===");
Notices.Success("全部图标生成完成");
#endif
}
#endregion
protected override void OnHide()
{
Game.Input.OnUICanceled -= OnUICanceled;
ItemList.List.OnClickItem -= OnClickItem;
}
protected override void OnDestroy()
{
base.OnDestroy();
}
}
}