2 คะแนน โดย GN⁺ 2024-08-17 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ImRAD เป็นเครื่องมือสร้าง GUI สำหรับ ImGui ที่สร้าง โค้ด C++ ซึ่งนำไปใช้ในแอปพลิเคชันได้ทันที และสามารถพาร์สกลับมาเพื่อแก้ไข UI ที่สร้างไว้ต่อไปได้
  • รองรับ data binding, event และการเพิ่มโค้ด UI ด้วยตนเอง โดยโค้ดที่สร้างขึ้นจะแยกด้วย comment marker ทำให้ผู้ใช้ยังใช้งานดีไซเนอร์ต่อได้แม้ใส่โค้ดของตนเองเข้าไป
  • ทำงานบน Windows, Linux, MacOS และโค้ดที่สร้างขึ้นทำงานได้บน Windows, Linux, MacOS, Android
  • เลย์เอาต์ใช้ SameLine, Spacing, NextColumn และ box layout แทนตำแหน่งแบบ absolute พร้อมรักษาความสัมพันธ์ parent-child และลำดับระหว่างวิดเจ็ต
  • ซอร์สของ ImRAD เป็น GPL แต่โค้ดที่เครื่องมือสร้างขึ้นและ imrad.h ที่โค้ดนั้นใช้งานได้รับการยกเว้นจาก GPL จึงรวมเข้าในโปรเจกต์โอเพนซอร์สหรือเชิงพาณิชย์ได้

บทบาทของ ImRAD และวิธีสร้างโค้ด

  • ImRAD เป็นเครื่องมือสร้าง GUI สำหรับไลบรารี ImGui
  • สร้างและพาร์ส โค้ด C++ ที่ใช้โดยตรงในแอปพลิเคชันได้
  • ต่างจากเครื่องมืออื่น ๆ ตรงที่รองรับเวิร์กโฟลว์ในการแก้ไข UI ที่สร้างขึ้นต่อเนื่อง
    • Data binding

      • Event
      • การเพิ่มโค้ด UI ด้วยตนเอง
      • โค้ดที่สร้างขึ้นจะถูกบันทึกเป็นไฟล์ .h และ .cpp และสามารถตรวจสอบได้รวดเร็วผ่าน code preview

แพลตฟอร์มที่รองรับและประเภทหน้าต่าง

  • ตัว ImRAD เองทำงานบน Windows, Linux, MacOS
  • โค้ดที่สร้างขึ้นทำงานบน Windows, Linux, MacOS, Android
  • รองรับการออกแบบหน้าต่างหลากหลายรูปแบบ
    • หน้าต่างแบบ floating, popup, modal popup
    • MainWindow ที่รวมการทำงานกับ GLFW
      • ImRAD สร้างการเรียก GLFW เพื่อซิงก์หน้าต่าง ImGui กับ title bar ของหน้าต่าง OS, แฟล็กการปรับขนาด, auto size ฯลฯ
    • Activity
      • หน้าต่างแบบไม่มีการตกแต่งที่เติมเต็มพื้นที่ viewport ทั้งหมด
      • แสดง activity ได้ครั้งละหนึ่งรายการเท่านั้น
      • ใช้กับแอป Android เป็นหลัก
  • มีเทมเพลตรวมอยู่ด้วย
    • main.cpp ทั่วไปบนฐาน GLFW
    • MainActivity.java, AndroidManifest.xml, main.cpp, CMakeLists.txt สำหรับ Android

วิดเจ็ตและฟังก์ชันเลย์เอาต์

  • รองรับวิดเจ็ต ImGui หลากหลาย
    • วิดเจ็ตพื้นฐาน เช่น Text, Checkbox, Combo, Button, Slider, ColorEdit
    • วิดเจ็ตคอนเทนเนอร์ เช่น Child, Table, CollapsingHeader, TreeNode, TabBar
    • วิดเจ็ต เช่น Splitter, DockSpace
    • การแก้ไข MenuBar และ context menu
    • CustomWidget ที่เรียกโค้ดวิดเจ็ตภายนอกได้
  • เลย์เอาต์ถูกสร้างโดยใช้ SameLine, Spacing, NextColumn แทน ตำแหน่งแบบ absolute
    • ทำให้วิดเจ็ตปฏิบัติตาม item spacing และ frame padding อย่างสม่ำเสมอ
    • ความสัมพันธ์ parent-child และลำดับของ child ที่สำคัญต่อวิดเจ็ตคอนเทนเนอร์อย่าง Table จะชัดเจน
    • รองรับการกำหนดตำแหน่งทางเลือกที่รักษาระยะสัมพันธ์จากมุมของ parent ที่เลือกไว้ ใช้กับวิดเจ็ต overlay ได้
  • รองรับ box layout
    • กลไกเลย์เอาต์ที่สร้างอยู่บนฟีเจอร์ของ ImGui
    • สามารถยืดวิดเจ็ตที่ปรับขนาดได้ในแนวนอนหรือแนวตั้ง
    • ใส่ spacer เพื่อสร้างการจัดแนวได้
    • ใช้ Table Layout Helper ที่สร้างเลย์เอาต์แนวนอนด้วย Table ที่มองไม่เห็นได้ด้วย

Binding, event และโค้ดผู้ใช้

  • เนื่องจาก ImGui เป็นไลบรารี GUI แบบ immediate mode สถานะของวิดเจ็ต เช่น input text หรือรายการใน combo box ต้องถูกตั้งค่าในโค้ดที่สร้างขึ้น ณ ตอนวาด และ ImRAD จัดการเรื่องนี้ด้วย property binding
  • ตัวแปรของคลาสสามารถจัดการได้ด้วย class wizard แบบง่าย หรือผ่านกล่องโต้ตอบ binding
  • เมื่อใช้ property binding UI ที่สร้างขึ้นจะทำงานแบบไดนามิกได้ ในขณะที่ยังออกแบบต่อได้
  • รองรับการสร้าง event handler และโค้ดสนับสนุน
    • ตัวอย่างเช่น modal dialog จะสร้างฟังก์ชันสมาชิก OpenPopup ให้อัตโนมัติ โดยมี lambda callback ที่ถูกเรียกเมื่อปิด
    • event handler แยกโค้ดประมวลผล event ของผู้ใช้ออกจากส่วนที่สร้างขึ้น เพื่อให้ดีไซเนอร์ยังทำงานต่อได้
  • โค้ดที่สร้างขึ้นถูกแยกด้วย comment marker
    • ผู้ใช้สามารถใส่โค้ดเพิ่มเติมรอบ ๆ โค้ดที่สร้างขึ้นได้
    • ใช้กับการเรียก popup ที่ขึ้นกับ draw หรือการคำนวณตัวแปรบางส่วนได้
    • สามารถใช้ CustomWidget เพื่อมอบหมายงานให้ callback ของผู้ใช้ได้ด้วย

การตั้งค่า สไตล์ และรูปแบบ runtime

  • Window configuration คือรูปแบบแปรผันของ UI ที่เปิดใช้งานได้ตอน runtime
    • มีประโยชน์กับแพลตฟอร์มที่ต่างกันหรือการหมุนหน้าจอ เป็นต้น
  • สไตล์คือการตั้งค่าที่รวมสี ตัวแปรสไตล์ และฟอนต์ไว้ด้วยกัน
    • นอกจากสไตล์พื้นฐานของ ImGui แล้ว ผู้ใช้สามารถกำหนดสไตล์ใหม่ได้
    • สไตล์สามารถบันทึกเป็นไฟล์ INI ใต้โฟลเดอร์ style ได้
  • dialog unit สามารถตั้งเป็นพิกเซลแบบไม่ขึ้นกับอุปกรณ์ได้
    • มีประโยชน์กับ Android และแอปที่รองรับ DPI
  • ImRAD ติดตามการเปลี่ยนแปลงของไฟล์ที่เปิดอยู่
    • ระหว่างออกแบบใน ImRAD ผู้ใช้สามารถแก้ไขไฟล์เดียวกันใน IDE ที่เลือกได้ด้วย
    • การเปลี่ยนแปลงสไตล์ INI จะแสดงผลทันทีเช่นกัน

Dependency และตัวเลือกของโค้ดที่สร้างขึ้น

  • โค้ดที่สร้างขึ้นสามารถใช้ในโปรเจกต์ได้ทันที และโดยพื้นฐานพึ่งพาเพียงไลบรารี ImGui กับเฮดเดอร์ประกอบ imrad.h เท่านั้น
  • ปัจจุบัน imrad.h มีทั้ง interface และ implementation
    • หากต้องการสร้าง implementation ใน main.cpp ให้ define IMRAD_H_IMPLEMENTATION ก่อน include
  • โค้ดที่สร้างขึ้นใช้ routine จัดรูปแบบ ImRad::Format
    • ใน C++20 โดยพื้นฐานจะ delegate ไปยัง std::format
    • หาก define IMRAD_WITH_FMT จะใช้ไลบรารี fmt ได้
    • หากไม่มีทั้งสองอย่าง จะใช้ routine จัดรูปแบบแบบง่ายที่ข้ามแฟล็ก formatting
  • ฟีเจอร์บางส่วนต้องการ dependency เพิ่มและการเปิดใช้งานอย่างชัดเจน
    • วิดเจ็ต MainWindow หรือ Image ต้องการไลบรารีเพิ่มเติม เช่น GLFW, STB
    • ต้อง define IMRAD_WITH_LOAD_TEXTURE
  • imrad.h สามารถใช้ไลบรารี zlib เพื่อโหลด asset จากไฟล์ zip ได้
    • เปิดใช้งานด้วย IMRAD_WITH_MINIZIP
  • สามารถสร้างโค้ดที่มีสตริงแปลภาษาได้
    • เมื่อคอมไพล์ imrad.h ด้วย IMRAD_WITH_GETTEXT จะสามารถแปลด้วย gettext/libintl ได้
    • สามารถใช้ libintl-lite ที่ไม่มี dependency ได้เช่นกัน

ไลเซนส์และการเผยแพร่

  • ซอร์สโค้ดของ ImRAD ใช้ ไลเซนส์ GPL
  • โค้ดที่เครื่องมือสร้างขึ้นได้รับการยกเว้นจาก GPL
    • สามารถรวมไว้ในโปรเจกต์โอเพนซอร์สหรือเชิงพาณิชย์ได้
    • ผู้ใช้เป็นผู้กำหนดไลเซนส์ของโค้ดที่สร้างขึ้น
  • imrad.h ที่โค้ดที่สร้างขึ้นใช้งานก็ได้รับการยกเว้นจาก GPL เช่นกัน
  • เวอร์ชันล่าสุดให้ clone repository แล้ว build ด้วย CMake
    • ต้องดึง submodule ในไดเรกทอรี 3rdparty มาด้วย
  • เวอร์ชันที่ค่อนข้างเก่าสามารถดาวน์โหลดได้จาก Releases
  • ดู tutorial และเอกสารโดยละเอียดได้ที่ wiki

1 ความคิดเห็น

 
GN⁺ 2024-08-17
ความคิดเห็นบน Hacker News
  • หนึ่งในส่วนที่น่าทึ่งที่สุดของโปรเจกต์นี้คือ มันมี parser ที่ทำเอง สำหรับอ่าน subset ของ C++ ที่ตัวมันเองสร้างได้
    ทั้งหมดทำเป็น header เดียว น่าประทับใจแต่ก็ดูบ้าบิ่นเหมือนกัน
    https://github.com/tpecholt/imrad/blob/main/src/cpp_parser.h

    • อยากรู้ว่าที่พูดมานี้หมายความว่าอะไรกันแน่
      ผมไม่ค่อยคุ้นกับการเขียนโปรแกรม เลยเข้าใจแค่ว่าโปรเจกต์นี้มีบางอย่างที่อ่านข้อมูลได้
      ช่วยอธิบายได้ไหมว่าทำไมเครื่องมือที่อ่าน C++ ได้ถึงยอดเยี่ยมขนาดนั้น
  • เจ๋งมาก อาจเป็นเพราะ ความคิดถึง Visual Basic ก็ได้ แต่สำหรับผมโปรเจกต์นี้เหมือนเชอร์รีบนหน้าเค้กของ imgui เลย

    • จนถึงตอนนี้ก็ยังไม่มีประสบการณ์ RAD ไหนที่เร็วกว่า Visual Basic 6
  • ถ้าทำเป็น แอป wasm HTML5 เพื่อให้สร้าง GUI ในเบราว์เซอร์ได้เร็ว ๆ แล้วคัดลอกผลลัพธ์ไปวางใน editor ได้ ก็น่าจะเจ๋ง
    เห็นบอกว่า “สร้างและ parse โค้ด C++ และโค้ดนี้สามารถนำไปใช้ในแอปพลิเคชันได้ทันที” เลยสงสัยว่า parse ในที่นี้คือการอ่านโค้ดที่ตัวเองสร้างขึ้นกลับเข้าไปใหม่หรือเปล่า

    • parser อยู่ที่นี่: https://github.com/tpecholt/imrad/blob/main/src/cpp_parser.h
      ดูเหมือนว่าจะเอาไว้อ่านโค้ดที่ตัวเองสร้างขึ้นจริง ๆ parser ที่ทำเองนี้ไม่ได้รองรับทั้งภาษา แต่รองรับแค่ subset เท่านั้น
      เช่น มีการ hardcode การรู้จำ STL container ไว้ และน่าจะจัดการเฉพาะสิ่งที่อาจปรากฏในโค้ดที่สร้างขึ้นเท่านั้น
      ในขั้นตอนนี้ไม่ได้สร้าง abstract syntax tree (AST) ดูเหมือนจะทำ tokenization กับ lexical analysis แล้วปล่อยให้ฝั่งผู้เรียกต้องเข้าใจเองว่าจะขับเคลื่อน “state machine” ของการ parse ต่ออย่างไร
      ส่วนการสร้าง AST และ code generation น่าจะอยู่ในไฟล์นี้ที่ยาวกว่า 9,000 บรรทัด: https://github.com/tpecholt/imrad/blob/main/src/node.cpp
    • ลืมวิธีติดตั้งและรันแอปเนทีฟไปแล้วหรือเปล่า? :)
      เขียนไว้ว่า “ImRAD รันได้บน Windows, Linux, MacOS”
    • แอป wasm HTML5 ดูจะไม่ค่อยเข้ากับแนวทางของไลบรารี imgui ที่พยายามทำงานแบบเนทีฟได้หลายแพลตฟอร์มและลด dependency ให้เหลือน้อยที่สุด
  • ยอดเยี่ยม ช่วงหลายปีที่ผ่านมาผมกำลังทำแอป ImGui C++ อยู่ ถ้ามีสิ่งนี้ตอนนั้นคงประหยัดเวลาได้มาก

    • ผมเพิ่งเริ่มใช้ imGui เลยอยากรู้ว่าสิ่งนี้ช่วยประหยัดเวลาได้อย่างไร
  • ถ้าผู้สร้าง dear-imgui บอกว่าชื่อคือ “dear” งั้นควรพูดว่า “for the Dear library” ไม่ใช่หรือ?
    IMGUI หมายถึง immediate mode GUI และ ocornut เคยบอกว่าได้รับแรงบันดาลใจจาก IMGUI อีกตัวที่ชื่อ “simgui”
    “หลังจากนั้นประมาณ 15 เดือนก็เปลี่ยนชื่อเป็น ‘dear imgui’ เพราะ ‘imgui’ ไปครอบครองตัวย่อทั้งหมดอยู่ ขอโทษที่ยังทำให้สับสนมาจนถึงตอนนี้”
    https://github.com/ocornut/imgui/issues/7892

    • Dear ImGui คือชื่อเต็มอย่างเป็นทางการ แต่การเรียกสั้น ๆ ว่า ImGui ก็ยังพบได้บ่อยมาก
      ชื่อ namespace ก็เป็น ImGui และไม่ใช่แค่ “Dear” อย่างเดียวแน่นอน
  • คิดว่าไม่ควรใส่ sudo ลงไปเยอะเกินไป นอกนั้นดูเจ๋งจริง ๆ

  • สงสัยว่า โค้ด C++ ที่สร้างขึ้นจะนำไปใช้ในที่อย่าง Python ตอนใช้ binding ของ pyimgui ได้ไหม

  • สงสัยว่าทำไม GUI builder สำหรับ ImGui ถึงไม่ได้สร้างด้วย ตัว ImGui เอง

    • ไม่รู้ว่าทำไมถึงคิดว่าไม่ใช่ ดูจากโค้ดและ screenshot แล้ว UI ใช้ Dear ImGui อยู่
  • เจ๋ง กำลังทำโปรเจกต์ด้วย ImGui อยู่ และคิดมาตลอดว่าน่าจะมีอะไรแบบนี้ จะลองใช้ดู

  • Steam เป็นระบบข้ามแพลตฟอร์มยอดนิยม ใช้กับแอปพลิเคชันที่ไม่ใช่เกมได้ไหม? หรือแม้แต่กับ แอปพลิเคชันระดับองค์กร ได้ไหม?

    • แอปพลิเคชันมักต้องการ การเรนเดอร์ข้อความและการรองรับ layout ที่ดี
      เช่น หลายบรรทัด ฟอนต์ และบางกรณีฟีเจอร์อย่าง RTL แต่ ImGUI ยังขาดด้านนี้อยู่
    • ไม่ค่อยแน่ใจว่าทำไมถึงยก Steam ขึ้นมา แต่ Steam ก็ขายซอฟต์แวร์เหมือนกัน