Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Plugin] Free Uxml to C# wrappers generator + logical templates

Discussion in 'UI Toolkit' started by Kamyker, Sep 12, 2019.

  1. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,085
    After discussion in uxml-could-be-easily-replaced-with-C# I've created simple tool to generate C# wrapper classes for uxml files.
    https://github.com/kamyker/UnityUxmlToCsharp

    Advance example from the bottom of readme:
    Page.uxml
    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <UXML
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.     xmlns="UnityEngine.UIElements"
    5.     xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    6.     xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
    7.     <Button style="--csName: TestButton1;"/>
    8.     <Button style="--csName: TestButton2;"/>
    9.     <Button style="--csName: TestButton3;"/>
    10. </UXML>
    PageConverted.cs is generated from uxml above.

    PageConvertedExtended.cs
    Code (CSharp):
    1. public class PageConvertedExtended : PageConverted
    2. {
    3.     private void PageConvertedExtended() //PageConverted constructor is called before this
    4.     {
    5.         TestButton1.clickable.clicked += () => Debug.Log("button1 clicked");
    6.         TestButton2.clickable.clicked += () => Debug.Log("button2 clicked");
    7.         TestButton3.clickable.clicked += () => Debug.Log("button3 clicked");
    8.      
    9.         TestButton1.RegisterCallback<GeometryChangedEvent>(OnWindowResized);
    10.     }
    11.  
    12.     private void OnWindowResized(GeometryChangedEvent window)
    13.     {
    14.         //using TestButton1, TestButton2, TestButton3 here
    15.     }
    16. }
    TriplePages.uxml
    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <UXML
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.     xmlns="UnityEngine.UIElements"
    5.     xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    6.     xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
    7.     <Box style="--csTemplate: PageConvertedExtended;">
    8.     <Box style="--csTemplate: PageConvertedExtended;">
    9.     <Box style="--csTemplate: PageConvertedExtended;">
    10. </UXML>
    This uxml is converted to TriplePagesConverted class. It also uses something similar to uxml templates but with logic included.

    TestWindow.cs
    Code (CSharp):
    1. public class TestWindow : EditorWindow
    2. {
    3.     private void OnEnable()
    4.     {
    5.         var root = rootVisualElement;
    6.         root.Clear();
    7.         root.AddChildrenOf(new TriplePagesConverted());
    8.     }
    9. }
     
    Last edited: Sep 12, 2019
    akihikodaki and MostHated like this.
  2. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    Are you at all familiar with Python and Qt/QtCreator and their .ui files? Seeing this reminded me of a tool I absolutely loved called pyuic which takes the Qt .ui file (which is xml) and just converts it to pure Python, eliminating the dependency on the original xml .ui file.

    Using Qt with pure Python without the .ui file is pretty similar to using UIElements with only C#, which makes me wonder if it is possible to take something like your tool you have already, and take it a step further similar to pyuic? I am not quite sure how you are doing things under the hood yet, as I only just came across it, but it instantly made me think of this.

    Would be pretty sweet to be able to just create the whole UI in UIBuilder, convert it, and ditch the uxml file.


    Code (CSharp):
    1.  
    2. <?xml version="1.0" encoding="UTF-8"?>
    3. <ui version="4.0">
    4. <class>BugReport</class>
    5. <widget class="QWidget" name="BugReport">
    6.   <property name="windowModality">
    7.    <enum>Qt::NonModal</enum>
    8.   </property>
    9.   <property name="geometry">
    10.    <rect>
    11.     <x>0</x>
    12.     <y>0</y>
    13.     <width>393</width>
    14.     <height>172</height>
    15.    </rect>
    16.   </property>
    17.   <property name="sizePolicy">
    18.    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    19.     <horstretch>0</horstretch>
    20.     <verstretch>0</verstretch>
    21.    </sizepolicy>
    22.   </property>
    23.   <property name="minimumSize">
    24.    <size>
    25.     <width>100</width>
    26.     <height>0</height>
    27.    </size>
    28.   </property>
    29.   <property name="baseSize">
    30.    <size>
    31.     <width>0</width>
    32.     <height>0</height>
    33.    </size>
    34.   </property>
    35.   <property name="windowTitle">
    36.    <string>Form</string>
    37.   </property>
    38.   <property name="styleSheet">
    39.    <string notr="true"/>
    40.   </property>
    41.   <layout class="QGridLayout" name="gridLayout">
    42.    <property name="bottomMargin">
    43.     <number>6</number>
    44.    </property>
    45.    <property name="spacing">
    46.     <number>6</number>
    47.    </property>
    48.    <item row="0" column="0">
    49.     <layout class="QVBoxLayout" name="verticalLayout_4">
    50.      <item>
    51.       <layout class="QHBoxLayout" name="horizontalLayout">
    52.        <item>
    53.         <layout class="QVBoxLayout" name="verticalLayout">
    54.          <item>
    55.           <layout class="QHBoxLayout" name="secondrow">
    56.            <item>
    57.             <widget class="QLineEdit" name="lineEdit">
    58.              <property name="minimumSize">
    59.               <size>
    60.                <width>175</width>
    61.                <height>0</height>
    62.               </size>
    63.              </property>
    64.              <property name="placeholderText">
    65.               <string>Name:</string>
    66.              </property>
    67.             </widget>
    68.            </item>
    69.           </layout>
    70.          </item>
    71.          <item>
    72.           <layout class="QHBoxLayout" name="headerrow">
    73.            <item>
    74.             <widget class="QLineEdit" name="lineEdit_2">
    75.              <property name="minimumSize">
    76.               <size>
    77.                <width>175</width>
    78.                <height>0</height>
    79.               </size>
    80.              </property>
    81.              <property name="placeholderText">
    82.               <string>Contact:</string>
    83.              </property>
    84.             </widget>
    85.            </item>
    86.           </layout>
    87.          </item>
    88.          <item>
    89.           <layout class="QHBoxLayout" name="horizontalLayout_2">
    90.            <item>
    91.             <widget class="QTextEdit" name="textEdit">
    92.              <property name="placeholderText">
    93.               <string>What was the issue?</string>
    94.              </property>
    95.             </widget>
    96.            </item>
    97.            <item>
    98.             <spacer name="verticalSpacer">
    99.              <property name="orientation">
    100.               <enum>Qt::Vertical</enum>
    101.              </property>
    102.              <property name="sizeHint" stdset="0">
    103.               <size>
    104.                <width>0</width>
    105.                <height>40</height>
    106.               </size>
    107.              </property>
    108.             </spacer>
    109.            </item>
    110.           </layout>
    111.          </item>
    112.         </layout>
    113.        </item>
    114.        <item>
    115.         <layout class="QVBoxLayout" name="verticalLayout_2">
    116.          <item>
    117.           <layout class="QHBoxLayout" name="horizontalLayout_3">
    118.            <item>
    119.             <widget class="QLabel" name="logo">
    120.              <property name="sizePolicy">
    121.               <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
    122.                <horstretch>0</horstretch>
    123.                <verstretch>0</verstretch>
    124.               </sizepolicy>
    125.              </property>
    126.              <property name="maximumSize">
    127.               <size>
    128.                <width>120</width>
    129.                <height>120</height>
    130.               </size>
    131.              </property>
    132.              <property name="text">
    133.               <string/>
    134.              </property>
    135.              <property name="pixmap">
    136.               <pixmap>C:/Users/mosthated/Downloads/483688212.png</pixmap>
    137.              </property>
    138.              <property name="scaledContents">
    139.               <bool>true</bool>
    140.              </property>
    141.             </widget>
    142.            </item>
    143.           </layout>
    144.          </item>
    145.          <item>
    146.           <layout class="QHBoxLayout" name="horizontalLayout_4">
    147.            <item>
    148.             <widget class="QPushButton" name="pushButton">
    149.              <property name="text">
    150.               <string>Submit Bug</string>
    151.              </property>
    152.             </widget>
    153.            </item>
    154.           </layout>
    155.          </item>
    156.         </layout>
    157.        </item>
    158.       </layout>
    159.      </item>
    160.     </layout>
    161.    </item>
    162.   </layout>
    163. </widget>
    164. <resources/>
    165. <connections/>
    166. </ui>
    167.  

    Code (CSharp):
    1.  
    2. from qtpy import QtCore, QtGui, QtWidgets
    3.  
    4. class Ui_BugReport(object):
    5.     def setupUi(self, BugReport):
    6.         BugReport.setObjectName("BugReport")
    7.         BugReport.setWindowModality(QtCore.Qt.NonModal)
    8.         BugReport.resize(393, 172)
    9.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
    10.         sizePolicy.setHorizontalStretch(0)
    11.         sizePolicy.setVerticalStretch(0)
    12.         sizePolicy.setHeightForWidth(BugReport.sizePolicy().hasHeightForWidth())
    13.         BugReport.setSizePolicy(sizePolicy)
    14.         BugReport.setMinimumSize(QtCore.QSize(100, 0))
    15.         BugReport.setBaseSize(QtCore.QSize(0, 0))
    16.         BugReport.setStyleSheet("")
    17.         self.gridLayout = QtWidgets.QGridLayout(BugReport)
    18.         self.gridLayout.setContentsMargins(-1, -1, -1, 6)
    19.         self.gridLayout.setSpacing(6)
    20.         self.gridLayout.setObjectName("gridLayout")
    21.         self.verticalLayout_4 = QtWidgets.QVBoxLayout()
    22.         self.verticalLayout_4.setObjectName("verticalLayout_4")
    23.         self.secondrow = QtWidgets.QHBoxLayout()
    24.         self.secondrow.setObjectName("secondrow")
    25.         self.title = QtWidgets.QLineEdit(BugReport)
    26.         self.title.setMinimumSize(QtCore.QSize(175, 0))
    27.         self.title.setObjectName("title")
    28.         self.secondrow.addWidget(self.title)
    29.         self.edittitle_btn = QtWidgets.QPushButton(BugReport)
    30.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
    31.         sizePolicy.setHorizontalStretch(0)
    32.         sizePolicy.setVerticalStretch(0)
    33.         sizePolicy.setHeightForWidth(self.edittitle_btn.sizePolicy().hasHeightForWidth())
    34.         self.edittitle_btn.setSizePolicy(sizePolicy)
    35.         self.edittitle_btn.setMaximumSize(QtCore.QSize(55, 16777215))
    36.         self.edittitle_btn.setObjectName("edittitle")
    37.         self.secondrow.addWidget(self.edittitle_btn)
    38.         self.verticalLayout_4.addLayout(self.secondrow)
    39.         self.webview = QtWidgets.QLabel(BugReport)
    40.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
    41.         sizePolicy.setHorizontalStretch(0)
    42.         sizePolicy.setVerticalStretch(0)
    43.         sizePolicy.setHeightForWidth(self.webview.sizePolicy().hasHeightForWidth())
    44.         self.webview.setSizePolicy(sizePolicy)
    45.         self.webview.setObjectName("webview")
    46.         self.verticalLayout_4.addWidget(self.webview)
    47.         self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1)
    48.         self.horizontalLayout = QtWidgets.QHBoxLayout()
    49.         self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
    50.         self.horizontalLayout.setObjectName("horizontalLayout")
    51.         spacerItem = QtWidgets.QSpacerItem(40, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
    52.         self.horizontalLayout.addItem(spacerItem)
    53.         self.continue_btn = QtWidgets.QPushButton(BugReport)
    54.         self.continue_btn.setObjectName("continue_btn")
    55.         self.horizontalLayout.addWidget(self.continue_btn)
    56.         self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
    57.  
    58.         self.retranslateUi(BugReport)
    59.         QtCore.QMetaObject.connectSlotsByName(BugReport)
    60.  
    61.     def retranslateUi(self, BugReport):
    62.         _translate = QtCore.QCoreApplication.translate
    63.         BugReport.setWindowTitle(_translate("BugReport", "Form"))
    64.         self.title.setPlaceholderText(_translate("BugReport", "Please enter descriptive bug report title"))
    65.         self.edittitle_btn.setText(_translate("BugReport", "Edit"))
    66.         self.webview.setText(_translate("BugReport", "TextLabel"))
    67.         self.continue_btn.setText(_translate("BugReport", "Continue"))
    68.  
     
    Last edited: Sep 12, 2020
  3. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,085
    Interesting, tbh I hope I won't have to touch uxml, uss files at all and just use editor as is the case with UGUI. We will see, waiting for stable release to try it out once again.