Unity 位图字体

下载Bitmap Font Generator

BMFont - AngelCode.com

解压后不用安装直接双击使用

提前设置

1、设置Bit depth为32

Options->Export options

2、清空所选字符

因为我们将在后边导入需要的字符。

Edit->Select all chars  先选择所有字符

Edit->Clear all chars in font  再清空所有字符

配置字符

1、打开Open Image Manager

Edit->Open Image Manager

2、配置字符和对应的字符图片

先准备这些字符的ASCII码

可以通过在线工具查询:ASCII编码转换,ASCII码在线查询工具

字符

ASCII码

0

48

1

49

2

50

3

51

4

52

5

53

6

54

7

55

8

56

9

57

.

46

+

43

-

45

K

75

M

77

G

71

点击Image->Import image,开始配置

返回主界面,查看标有小亮点的字符为已配置成功的字符

导出文件

导出前可以预览一下 Options->Visualize

直接导出

Options->Save bitmap font as....

导出成功

导入Unity使用

创建下面两个脚本,将其放到Editor文件夹下

using UnityEngine;
using UnityEditor;
using System;
using System.IO;

public class BFImporter : AssetPostprocessor
{
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        foreach (string str in importedAssets)
        {
            DoImportBitmapFont(str);
        }
        foreach (string str in deletedAssets)
        {
            DelBitmapFont(str);
        }

        for (var i = 0; i < movedAssets.Length; i++)
        {
            MoveBitmapFont(movedFromAssetPaths[i], movedAssets[i]);
        }
    }

    public static bool IsFnt(string path)
    {
        return path.EndsWith(".fnt", StringComparison.OrdinalIgnoreCase);
    }

    public static void DoImportBitmapFont(string fntPath)
    {
        if (!IsFnt(fntPath)) return;

        TextAsset fnt = AssetDatabase.LoadMainAssetAtPath(fntPath) as TextAsset;
        string text = fnt.text;
        FntParse parse = FntParse.GetFntParse(ref text);
        if (parse == null) return;

        string fntName = Path.GetFileNameWithoutExtension(fntPath);
        string rootPath = Path.GetDirectoryName(fntPath);
        string fontPath = string.Format("{0}/{1}.fontsettings", rootPath, fntName);
        Texture2D[] textures = DoImportTextures(parse, rootPath, fnt);
        if (textures.Length > 1)
        {
            Debug.LogError(fntPath + " has more than one texture!");
        }

        Font font = AssetDatabase.LoadMainAssetAtPath(fontPath) as Font;
        if (font == null)
        {
            font = new Font();
            AssetDatabase.CreateAsset(font, fontPath);
            AssetDatabase.WriteImportSettingsIfDirty(fontPath);
            AssetDatabase.ImportAsset(fontPath);
        }
        Material material = AssetDatabase.LoadAssetAtPath(fontPath, typeof(Material)) as Material;
        if (material == null)
        {
            material = new Material(Shader.Find("UI/Default"));
            material.name = "Font Material";
            AssetDatabase.AddObjectToAsset(material, fontPath);
            // unity 5.4+ cannot refresh it immediately, must import it
            AssetDatabase.ImportAsset(fontPath);
        }
        font.material = material;
        material.mainTexture = textures[0];
        font.characterInfo = parse.charInfos;

        SerializedObject so = new SerializedObject(font);
        so.Update();
        so.FindProperty("m_FontSize").floatValue = Mathf.Abs(parse.fontSize);
        so.FindProperty("m_LineSpacing").floatValue = parse.lineHeight;
        so.FindProperty("m_Ascent").floatValue = parse.lineBaseHeight;
        SerializedProperty prop = so.FindProperty("m_Descent");
        if (prop != null)
            prop.floatValue = parse.lineBaseHeight - parse.lineHeight;
        UpdateKernings(so, parse.kernings);
        so.ApplyModifiedProperties();
        so.SetIsDifferentCacheDirty();

        AssetDatabase.DeleteAsset(fntPath);
        AssetDatabase.SaveAssets();
        
        // unity 5.5 can not load custom font
        ReloadFont(fontPath);
    }

    private static Texture2D[] DoImportTextures(FntParse parse, string rootPath, TextAsset fnt)
    {
        int len = parse.textureNames.Length;
        Texture2D[] textures = new Texture2D[len];
        for (int i = 0; i < len; i++)
        {
            string texPath = string.Format("{0}/{1}", rootPath, parse.textureNames[i]);

            Texture2D texture = AssetDatabase.LoadMainAssetAtPath(texPath) as Texture2D;
            if (texture == null)
            {
                Debug.LogErrorFormat(fnt, "{0}: not found '{1}'.", typeof(BFImporter), texPath);
                return textures;
            }

            TextureImporter texImporter = AssetImporter.GetAtPath(texPath) as TextureImporter;
            texImporter.textureType = TextureImporterType.GUI;
            texImporter.mipmapEnabled = false;
            texImporter.SaveAndReimport();
            textures[i] = texture;
        }
        return textures;
    }

    private static void UpdateKernings(SerializedObject so, Kerning[] kernings)
    {
        int len = kernings != null ? kernings.Length : 0;
        SerializedProperty kerningsProp = so.FindProperty("m_KerningValues");

        if (len == 0)
        {
            kerningsProp.ClearArray();
            return;
        }

        int propLen = kerningsProp.arraySize;
        for (int i = 0; i < len; i++)
        {
            if (propLen <= i)
            {
                kerningsProp.InsertArrayElementAtIndex(i);
            }

            SerializedProperty kerningProp = kerningsProp.GetArrayElementAtIndex(i);
            kerningProp.FindPropertyRelative("second").floatValue = kernings[i].amount;
            SerializedProperty pairProp = kerningProp.FindPropertyRelative("first");
            pairProp.Next(true);
            pairProp.intValue = kernings[i].first;
            pairProp.Next(false);
            pairProp.intValue = kernings[i].second;
        }
        for (int i = propLen - 1; i >= len; i--)
        {
            kerningsProp.DeleteArrayElementAtIndex(i);
        }
    }

    private static void DelBitmapFont(string fntPath)
    {
        if (!IsFnt(fntPath)) return;

        string fontPath = fntPath.Substring(0, fntPath.Length - 4) + ".fontsettings";
        AssetDatabase.DeleteAsset(fontPath);
    }

    private static void MoveBitmapFont(string oldFntPath, string nowFntPath)
    {
        if (!IsFnt(nowFntPath)) return;

        string oldFontPath = oldFntPath.Substring(0, oldFntPath.Length - 4) + ".fontsettings";
        string nowFontPath = nowFntPath.Substring(0, nowFntPath.Length - 4) + ".fontsettings";
        AssetDatabase.MoveAsset(oldFontPath, nowFontPath);
    }

    // new font can not display via Text in unity 5.5
    // must import import it
    private static void ReloadFont(string fontPath)
    {
        var tmpPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
        AssetDatabase.ExportPackage(fontPath, tmpPath);
        AssetDatabase.DeleteAsset(fontPath);

        var startTime = DateTime.Now;
        EditorApplication.CallbackFunction func = null;
        func = () =>
        {
            TimeSpan dalt = DateTime.Now - startTime;
            if (dalt.TotalSeconds >= 0.1)
            {
                EditorApplication.update -= func;
                AssetDatabase.ImportPackage(tmpPath, false);
                File.Delete(tmpPath);
            }
        };

        EditorApplication.update += func;
    }
}
 
using UnityEngine;
using System.Xml;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public struct Kerning
{
    public int first;
    public int second;
    public int amount;
}

public class FntParse
{
    public int textureWidth;
    public int textureHeight;
    public string[] textureNames;

    public string fontName;
    public int fontSize;
    public int lineHeight;
    public int lineBaseHeight;

    public CharacterInfo[] charInfos { get; private set; }
    public Kerning[] kernings { get; private set; }

    public static FntParse GetFntParse(ref string text)
    {
        FntParse parse = null;
        if (text.StartsWith("info"))
        {
            parse = new FntParse();
            parse.DoTextParse(ref text);
        }
        else if (text.StartsWith("<"))
        {
            parse = new FntParse();
            parse.DoXMLPase(ref text);
        }
        return parse;
    }

    #region xml
    public void DoXMLPase(ref string content)
    {
        XmlDocument xml = new XmlDocument();
        xml.LoadXml(content);

        XmlNode info = xml.GetElementsByTagName("info")[0];
        XmlNode common = xml.GetElementsByTagName("common")[0];
        XmlNodeList pages = xml.GetElementsByTagName("pages")[0].ChildNodes;
        XmlNodeList chars = xml.GetElementsByTagName("chars")[0].ChildNodes;


        fontName = info.Attributes.GetNamedItem("face").InnerText;
        fontSize = ToInt(info, "size");

        lineHeight = ToInt(common, "lineHeight");
        lineBaseHeight = ToInt(common, "base");
        textureWidth = ToInt(common, "scaleW");
        textureHeight = ToInt(common, "scaleH");
        int pageNum = ToInt(common, "pages");
        textureNames = new string[pageNum];

        for (int i = 0; i < pageNum; i++)
        {
            XmlNode page = pages[i];
            int pageId = ToInt(page, "id");
            textureNames[pageId] = page.Attributes.GetNamedItem("file").InnerText;
        }

        charInfos = new CharacterInfo[chars.Count];
        for (int i = 0; i < chars.Count; i++)
        {
            XmlNode charNode = chars[i];
            charInfos[i] = CreateCharInfo(
                ToInt(charNode, "id"),
                ToInt(charNode, "x"),
                ToInt(charNode, "y"),
                ToInt(charNode, "width"),
                ToInt(charNode, "height"),
                ToInt(charNode, "xoffset"),
                ToInt(charNode, "yoffset"),
                ToInt(charNode, "xadvance"),
                ToInt(charNode, "page"));
        }

        // kernings
        XmlNode kerningsNode = xml.GetElementsByTagName("kernings")[0];
        if (kerningsNode != null && kerningsNode.HasChildNodes)
        {
            XmlNodeList kerns = kerningsNode.ChildNodes;
            kernings = new Kerning[kerns.Count];
            for (int i = 0; i < kerns.Count; i++)
            {
                XmlNode kerningNode = kerns[i];
                kernings[i] = new Kerning();
                kernings[i].first = ToInt(kerningNode, "first");
                kernings[i].second = ToInt(kerningNode, "second");
                kernings[i].amount = ToInt(kerningNode, "amount");
            }
        }
    }
    
    private static int ToInt(XmlNode node, string name)
    {
        return int.Parse(node.Attributes.GetNamedItem(name).InnerText);
    }
    #endregion

    #region text
    private Regex pattern;
    public void DoTextParse(ref string content)
    {
        // letter=" "       // \S+=".+?"
        // letter="x"       // \S+=".+?"
        // letter="""       // \S+=".+?"
        // letter=""        // \S+
        // char             // \S+
        pattern = new Regex(@"\S+="".+?""|\S+");
        string[] lines = content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        ReadTextInfo(ref lines[0]);
        ReadTextCommon(ref lines[1]);

        for (int j = 0; j < textureNames.Length; j++)
        {
            ReadTextPage(ref lines[j + 2]);
        }

        // don't use count of chars, count is incorrect if has space 
        //ReadTextCharCount(ref lines[3]);
        List<CharacterInfo> list = new List<CharacterInfo>();
        int i = 2 + textureNames.Length;
        int l = lines.Length;
        for (; i < l; i++)
        {
            if (!ReadTextChar(i - 4, ref lines[i], ref list))
                break;
        }
        charInfos = list.ToArray();

        // skip empty line
        for (; i < l; i++)
        {
            if (lines[i].Length > 0)
                break;
        }

        // kernings
        if (i < l)
        {
            int count = 0;
            if (ReadTextCount(ref lines[i++], out count))
            {
                int start = i;
                kernings = new Kerning[count];
                for (; i < l; i++)
                {
                    if (!ReadTextKerning(i - start, ref lines[i], ref list))
                        break;
                }
            };
        }
    }

    private void ReadTextInfo(ref string line)
    {
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "face": fontName = values[i]; break;
                case "size": fontSize = int.Parse(values[i]); break;
            }
        }
    }

    private void ReadTextCommon(ref string line)
    {
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "lineHeight": lineHeight = int.Parse(values[i]); break;
                case "base": lineBaseHeight = int.Parse(values[i]); break;
                case "scaleW": textureWidth = int.Parse(values[i]); break;
                case "scaleH": textureHeight = int.Parse(values[i]); break;
                case "pages": textureNames = new string[int.Parse(values[i])]; break;
            }
        }
    }

    private void ReadTextPage(ref string line)
    {
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        string textureName = null;
        int pageId = -1;
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "file": textureName = values[i]; break;
                case "id": pageId = int.Parse(values[i]); break;
            }
        }
        textureNames[pageId] = textureName;
    }

    private bool ReadTextCount(ref string line, out int count)
    {
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        count = 0;
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "count":
                    count = int.Parse(values[i]);
                    return true;
            }
        }
        return false;
    }

    private bool ReadTextChar(int idx, ref string line, ref List<CharacterInfo> list)
    {
        if (!line.StartsWith("char")) return false;
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        int id = 0, x = 0, y = 0, w = 0, h = 0, xo = 0, yo = 0, xadvance = 0;
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "id": id = int.Parse(values[i]); break;
                case "x": x = int.Parse(values[i]); break;
                case "y": y = int.Parse(values[i]); break;
                case "width": w = int.Parse(values[i]); break;
                case "height": h = int.Parse(values[i]); break;
                case "xoffset": xo = int.Parse(values[i]); break;
                case "yoffset": yo = int.Parse(values[i]); break;
                case "xadvance": xadvance = int.Parse(values[i]); break;
            }
        }
        list.Add(CreateCharInfo(id, x, y, w, h, xo, yo, xadvance));
        return true;
    }

    private bool ReadTextKerning(int idx, ref string line, ref List<CharacterInfo> list)
    {
        if (!line.StartsWith("kerning")) return false;
        string[] keys;
        string[] values;
        SplitParts(line, out keys, out values);
        Kerning kerning = new Kerning();
        for (int i = keys.Length - 1; i >= 0; i--)
        {
            switch (keys[i])
            {
                case "first": kerning.first = int.Parse(values[i]); break;
                case "second": kerning.second = int.Parse(values[i]); break;
                case "amount": kerning.amount = int.Parse(values[i]); break;
            }
        }
        kernings[idx] = kerning;
        return true;
    }

    private bool SplitParts(string line, out string[] keys, out string[] values)
    {
        MatchCollection parts = pattern.Matches(line);
        int count = parts.Count;
        keys = new string[count - 1];
        values = new string[count - 1];
        for (int i = count - 2; i >= 0; i--)
        {
            string part = parts[i + 1].Value;
            int pos = part.IndexOf('=');
            keys[i] = part.Substring(0, pos);
            values[i] = part.Substring(pos + 1).Trim('"');
        }
        return true;
    }

    #endregion

    private CharacterInfo CreateCharInfo(int id, int x, int y, int w, int h, int xo, int yo, int xadvance, int page = 0)
    {
        Rect uv = new Rect();
        uv.x = (float)x / textureWidth + page;
        uv.y = (float)y / textureHeight;
        uv.width = (float)w / textureWidth;
        uv.height = (float)h / textureHeight;
        uv.y = 1f - uv.y - uv.height;

        Rect vert = new Rect();
        vert.x = xo;
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2
        // unity 5.0 can not support baseline for 
        vert.y = yo;
#else
        vert.y = yo - lineBaseHeight;
#endif
        vert.width = w;
        vert.height = h;
        vert.y = -vert.y;
        vert.height = -vert.height;

        CharacterInfo charInfo = new CharacterInfo();
        charInfo.index = id;

#if UNITY_5_3_OR_NEWER || UNITY_5_3 || UNITY_5_2
        charInfo.uvBottomLeft = new Vector2(uv.xMin, uv.yMin);
        charInfo.uvBottomRight = new Vector2(uv.xMax, uv.yMin);
        charInfo.uvTopLeft = new Vector2(uv.xMin, uv.yMax);
        charInfo.uvTopRight = new Vector2(uv.xMax, uv.yMax);

        charInfo.minX = (int)vert.xMin;
        charInfo.maxX = (int)vert.xMax;
        charInfo.minY = (int)vert.yMax;
        charInfo.maxY = (int)vert.yMin;

        charInfo.bearing = (int)vert.x;
        charInfo.advance = xadvance;
#else
#pragma warning disable 618
        charInfo.uv = uv;
        charInfo.vert = vert;
        charInfo.width = xadvance;
#pragma warning restore 618
#endif
        return charInfo;
    }
}

将这两个文件直接拖入Unity中,系统自动生成字体文件

直接使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973393.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

双重差分学习笔记

双重差分适用的研究场景&#xff1a; 研究某项政策或者冲击造成的影响 例如&#xff0c;某某小学在2024.12.12日颁布了小红花激励措施&#xff0c;我们要研究这项措施对学生成绩的影响&#xff0c;此时&#xff0c;就可以使用双重差分模型。 双重差分适用的数据类型&#xf…

项目设置内网 IP 访问实现方案

在我们平常的开发工作中&#xff0c;项目开发、测试完成后进行部署上线。比如电商网站、新闻网站、社交网站等&#xff0c;通常对访问不会进行限制。但是像企业内部网站、内部管理系统等&#xff0c;这种系统一般都需要限制访问&#xff0c;比如内网才能访问等。那么一个网站应…

数仓搭建(hive):DWB层(基础数据层)

维度退化: 通过减少表的数量和提高数据的冗余来优化查询性能。 在维度退化中&#xff0c;相关的维度数据被合并到一个宽表中&#xff0c;减少了查询时需要进行的表连接操作。例如&#xff0c;在销售数据仓库中&#xff0c;客户信息、产品信息和时间信息等维度可能会被合并到一…

多模态特征提取与融合助力高光谱+LiDAR数据分类性能飞跃

目录 论文解读 总体架构 CMIIE 模块工作模式 MLFFC模块工作模式 论文解读 提出了一种新的多模态特征提取模块CMIIE,可以捕获高光谱和LiDAR数据之间的互补信息。设计了一个多层特征融合分类模块MLFFC,通过对不同层级的特征进行融合来提高分类性能。使用对抗学习策略来指导网…

Flutter 正在推进全新 PlatformView 实现 HCPP, 它又用到了 Android 上的什么黑科技

跨平台开发里的 PlatformView 实现一直是一个经久不衰的话题&#xff0c;在之前的 《深入 Flutter 和 Compose 的 PlatformView 实现对比》 我们就详细聊过 Flutter 和 Compose 在 PlatformView 实现上的异同之处&#xff0c;也聊到了 Compose 为什么在相同实现上对比 Flutter …

Qt/C++面试【速通笔记一】

Qt 信号与槽机制 什么是信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;&#xff1f; 在Qt中&#xff0c;信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;是实现对象之间通信的一种机制。信号是对象在某些事件发生时发出的通知&…

《跟李沐学 AI》AlexNet论文逐段精读学习心得 | PyTorch 深度学习实战

前一篇文章&#xff0c;使用 AlexNet 实现图片分类 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于学习 9年后重读深度学习奠基作之一&#xff1a;AlexNet【下】【论文精读】】的心得。 《跟李沐…

【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin scatter plot Venn)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载画图1画图2画图3画图4画图5画图6画图7参考介绍 【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin & scatter plot & Venn) 加载R包 library…

IMX6ULL的ALT0、ALT1、ALT2、ALT3、ALT4等是啥意思?

在IMX6ULL的手册IMX6ULLRM.pdf中&#xff0c;发现了题目中这些描述&#xff0c;相关截图如下&#xff1a; 那么红框中的ALT0、ALT1、ALT2、ALT3、ALT4等是啥意思呢&#xff1f; 在IMX6ULL及其他NXP&#xff08;Freescale&#xff09;芯片中&#xff0c;ALT0、ALT1、ALT2、ALT…

Android Http-server 本地 web 服务

时间&#xff1a;2025年2月16日 地点&#xff1a;深圳.前海湾 需求 我们都知道 webview 可加载 URI&#xff0c;他有自己的协议 scheme&#xff1a; content:// 标识数据由 Content Provider 管理file:// 本地文件 http:// 网络资源 特别的&#xff0c;如果你想直接…

DeepSeek 冲击(含本地化部署实践)

DeepSeek无疑是春节档最火爆的话题&#xff0c;上线不足一月&#xff0c;其全球累计下载量已达4000万&#xff0c;反超ChatGPT成为全球增长最快的AI应用&#xff0c;并且完全开源。那么究竟DeepSeek有什么魔力&#xff0c;能够让大家趋之若鹜&#xff0c;他又将怎样改变世界AI格…

神经网络八股(1)

1.什么是有监督学习&#xff0c;无监督学习 有监督学习是带有标签的&#xff0c;无监督学习是没有标签的&#xff0c;简单来说就是有监督学习的输入输出都是固定的&#xff0c;已知的&#xff0c;无监督学习输入是已知的&#xff0c;输出是不固定的&#xff0c;无监督学习是通…

DeepSeek 助力 Vue 开发:打造丝滑的瀑布流布局(Masonry Layout)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

【分布式理论14】分布式数据库存储:分表分库、主从复制与数据扩容策略

文章目录 一、分表分库1. 数据分表的必要性与方式2. 数据分库原则与优势 二、主从复制1. 读写分离架构设计2. 数据复制方式3. MySQL实现主从复制4. MySQL主从复制实践与高可用方案 三、数据扩容 随着业务的不断发展和数据量的增长&#xff0c;传统的单机关系型数据库已经逐渐不…

从传统到轻量级5G:网络架构演变与优化路径

轻量级5G​​​​ 随着5G技术的不断发展&#xff0c;通信网络架构正经历着前所未有的变革。传统的5G核心网架构虽然在性能和容量方面表现出色&#xff0c;但在灵活性、部署效率以及成本控制方面却面临一些挑战。为了应对日益复杂的通信需求&#xff0c;轻量级5G核心网成为了一种…

搭建Kubernetes (K8s) 集群----Centos系统

前期准备 准备3台Linux虚拟机&#xff08;CentOS系统&#xff09;&#xff0c;参考 https://carry.blog.csdn.net/article/details/144578009https://carry.blog.csdn.net/article/details/144578009搭建Docker环境&#xff0c;参考 https://carry.blog.csdn.net/article/de…

OpenSSL实验

文章目录 一、OpenSSL安装二、OpenSSL配置常见路径查找配置文件的方法示例**1. 配置文件结构****2. 主要段落及其作用****(1) 默认段&#xff08;Default Section&#xff09;****(2) OID段&#xff08;OID Section&#xff09;****(3) CA相关段&#xff08;CA Section&#xf…

51单片机-按键

1、独立按键 1.1、按键介绍 轻触开关是一种电子开关&#xff0c;使用时&#xff0c;轻轻按开关按钮就可使开关接通&#xff0c;当松开手时&#xff0c;开关断开。 1.2、独立按键原理 按键在闭合和断开时&#xff0c;触点会存在抖动现象。P2\P3\P1都是准双向IO口&#xff0c;…

DeepSeek动画视频全攻略:从架构到本地部署

DeepSeek 本身并不直接生成动画视频,而是通过与一系列先进的 AI 工具和传统软件协作,完成动画视频的制作任务。这一独特的架构模式,使得 DeepSeek 在动画视频创作领域发挥着不可或缺的辅助作用。其核心流程主要包括脚本生成、画面设计、视频合成与后期处理这几个关键环节。 …

EasyRTC智能硬件:实时畅联、沉浸互动、消音护航

在当今智能硬件迅猛发展的时代&#xff0c;音视频通讯技术已成为设备与用户、设备与设备间不可或缺的沟通纽带。而EasyRTC&#xff0c;凭借其无可比拟的实时性能、卓越的互动感受以及强大的交互实力&#xff0c;正逐步演变为智能硬件领域的“超级动力”核心。特别是其倾力打造的…