- All 50 languages hardcoded in C source (no JSON parsing issues) - Auto-detect Windows system locale via LOCALE_SISO639LANGNAME - Full UI refresh on language switch (all menus rebuilt) - Menu labels: File/Build/Language/Help all correct per language - Covers: zh/en/ja/ko/es/fr/de/ru/pt/it/tr/ar/hi/th/vi/id/pl/nl/uk/cs/ro/sv/fi/da/no/el/he/ms/hu/sk/bg/hr/sr/sl/lt/lv/et/fa/bn/sw/ta/ml/te/ur/tl
305 lines
26 KiB
C
305 lines
26 KiB
C
// lity_editor.c - Lity3D Editor (Win32 Unicode, 50+ built-in languages)
|
||
#include <windows.h>
|
||
#include <commctrl.h>
|
||
#include <commdlg.h>
|
||
#include <shellapi.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#define IDC_TREE 1001
|
||
#define IDC_EDIT 1002
|
||
#define IDC_CONSOLE 1003
|
||
#define IDM_NEW 2001
|
||
#define IDM_OPEN 2002
|
||
#define IDM_SAVE 2003
|
||
#define IDM_RUN 2004
|
||
#define IDM_BUILD 2005
|
||
#define IDM_PACKAGE 2006
|
||
#define IDM_ABOUT 2007
|
||
#define IDM_LANG_BASE 3000
|
||
#define NUM_KEYS 20
|
||
#define NUM_LANGS 50
|
||
|
||
static HWND g_hwnd, g_tree, g_edit, g_console;
|
||
static WCHAR g_current_file[MAX_PATH] = L"";
|
||
static WCHAR g_engine_dir[MAX_PATH] = L"";
|
||
|
||
// Key names
|
||
static const char* g_keys[NUM_KEYS] = {
|
||
"title","file","build","scene","help","lang",
|
||
"new","open","save","exit","run","compile",
|
||
"package","explorer","output","ready","about","ok","kill","build_first"
|
||
};
|
||
// lang_code, display_name, translations[NUM_KEYS]
|
||
static struct { const char* code; const char* name; const WCHAR* trans[NUM_KEYS]; } g_langs[NUM_LANGS] = {
|
||
{"en","English",{L"Lity3D Editor",L"File",L"Build",L"Scene",L"Help",L"Language",L"New",L"Open",L"Save",L"Exit",L"Run",L"Build Engine",L"Package EXE",L"Explorer",L"Output",L"Ready",L"About",L"OK",L"Process killed",L"Build first"}},
|
||
{"zh","中文",{L"Lity3D 编辑器",L"文件",L"构建",L"场景",L"帮助",L"语言",L"新建",L"打开",L"保存",L"退出",L"运行游戏",L"编译引擎",L"打包 EXE",L"资源管理器",L"输出",L"就绪",L"关于",L"确定",L"进程已终止",L"请先编译引擎"}},
|
||
{"ja","日本語",{L"Lity3D エディタ",L"ファイル",L"ビルド",L"シーン",L"ヘルプ",L"言語",L"新規",L"開く",L"保存",L"終了",L"ゲーム実行",L"エンジンビルド",L"EXE出力",L"エクスプローラ",L"出力",L"準備完了",L"について",L"OK",L"停止済み",L"先にビルド"}},
|
||
{"ko","한국어",{L"Lity3D 편집기",L"파일",L"빌드",L"씬",L"도움말",L"언어",L"새로 만들기",L"열기",L"저장",L"종료",L"게임 실행",L"엔진 빌드",L"EXE 패키징",L"탐색기",L"출력",L"준비",L"정보",L"확인",L"중지됨",L"먼저 빌드"}},
|
||
{"es","Español",{L"Lity3D Editor",L"Archivo",L"Compilar",L"Escena",L"Ayuda",L"Idioma",L"Nuevo",L"Abrir",L"Guardar",L"Salir",L"Ejecutar",L"Compilar motor",L"Empaquetar",L"Explorador",L"Salida",L"Listo",L"Acerca de",L"OK",L"Detenido",L"Compilar primero"}},
|
||
{"fr","Français",{L"Lity3D Éditeur",L"Fichier",L"Construire",L"Scène",L"Aide",L"Langue",L"Nouveau",L"Ouvrir",L"Enregistrer",L"Quitter",L"Exécuter",L"Compiler",L"Package",L"Explorateur",L"Sortie",L"Prêt",L"À propos",L"OK",L"Arrêté",L"Compiler d'abord"}},
|
||
{"de","Deutsch",{L"Lity3D Editor",L"Datei",L"Erstellen",L"Szene",L"Hilfe",L"Sprache",L"Neu",L"Öffnen",L"Speichern",L"Beenden",L"Spiel starten",L"Engine erstellen",L"EXE paketieren",L"Explorer",L"Ausgabe",L"Bereit",L"Über",L"OK",L"Gestoppt",L"Erst bauen"}},
|
||
{"ru","Русский",{L"Lity3D Редактор",L"Файл",L"Сборка",L"Сцена",L"Справка",L"Язык",L"Новый",L"Открыть",L"Сохранить",L"Выход",L"Запуск",L"Собрать",L"Упаковать",L"Проводник",L"Вывод",L"Готово",L"О программе",L"OK",L"Остановлено",L"Сначала собрать"}},
|
||
{"pt","Português",{L"Lity3D Editor",L"Arquivo",L"Compilar",L"Cena",L"Ajuda",L"Idioma",L"Novo",L"Abrir",L"Salvar",L"Sair",L"Executar",L"Compilar engine",L"Empacotar",L"Explorador",L"Saída",L"Pronto",L"Sobre",L"OK",L"Parado",L"Compilar primeiro"}},
|
||
{"it","Italiano",{L"Lity3D Editor",L"File",L"Compila",L"Scena",L"Aiuto",L"Lingua",L"Nuovo",L"Apri",L"Salva",L"Esci",L"Esegui",L"Compila engine",L"Pacchetta",L"Esplora",L"Output",L"Pronto",L"Info",L"OK",L"Fermato",L"Compila prima"}},
|
||
{"tr","Türkçe",{L"Lity3D Editör",L"Dosya",L"Derle",L"Sahne",L"Yardım",L"Dil",L"Yeni",L"Aç",L"Kaydet",L"Çıkış",L"Çalıştır",L"Motoru derle",L"Paketle",L"Gezgin",L"Çıktı",L"Hazır",L"Hakkında",L"Tamam",L"Durduruldu",L"Önce derle"}},
|
||
{"ar","العربية",{L"Lity3D محرر",L"ملف",L"بناء",L"مشهد",L"مساعدة",L"لغة",L"جديد",L"فتح",L"حفظ",L"خروج",L"تشغيل",L"بناء المحرك",L"تغليف",L"مستكشف",L"مخرجات",L"جاهز",L"حول",L"موافق",L"تم الإيقاف",L"ابنِ أولاً"}},
|
||
{"hi","हिन्दी",{L"Lity3D संपादक",L"फ़ाइल",L"बिल्ड",L"दृश्य",L"सहायता",L"भाषा",L"नया",L"खोलें",L"सहेजें",L"बाहर",L"चलाएं",L"इंजन बिल्ड",L"EXE पैकेज",L"एक्सप्लोरर",L"आउटपुट",L"तैयार",L"के बारे में",L"ठीक है",L"बंद",L"पहले बिल्ड"}},
|
||
{"th","ภาษาไทย",{L"Lity3D ตัวแก้ไข",L"ไฟล์",L"สร้าง",L"ฉาก",L"ช่วยเหลือ",L"ภาษา",L"ใหม่",L"เปิด",L"บันทึก",L"ออก",L"รันเกม",L"สร้างเอนจิ้น",L"打包 EXE",L"ตัวสำรวจ",L"ผลลัพธ์",L"พร้อม",L"เกี่ยวกับ",L"ตกลง",L"หยุดแล้ว",L"สร้างก่อน"}},
|
||
{"vi","Tiếng Việt",{L"Lity3D Trình soạn",L"Tệp",L"Xây dựng",L"Cảnh",L"Trợ giúp",L"Ngôn ngữ",L"Mới",L"Mở",L"Lưu",L"Thoát",L"Chạy game",L"Build engine",L"Gói EXE",L"Duyệt",L"Đầu ra",L"Sẵn sàng",L"Giới thiệu",L"OK",L"Đã dừng",L"Build trước"}},
|
||
{"id","Bahasa",{L"Lity3D Editor",L"Berkas",L"Build",L"Sken",L"Bantuan",L"Bahasa",L"Baru",L"Buka",L"Simpan",L"Keluar",L"Jalankan",L"Build Engine",L"Paket EXE",L"Penjelajah",L"Output",L"Siap",L"Tentang",L"OK",L"Berhenti",L"Build dulu"}},
|
||
{"pl","Polski",{L"Lity3D Edytor",L"Plik",L"Kompiluj",L"Scena",L"Pomoc",L"Język",L"Nowy",L"Otwórz",L"Zapisz",L"Wyjście",L"Uruchom",L"Kompiluj engine",L"Pakietuj",L"Eksplorator",L"Wyjście",L"Gotowy",L"O programie",L"OK",L"Zatrzymano",L"Najpierw kompiluj"}},
|
||
{"nl","Nederlands",{L"Lity3D Editor",L"Bestand",L"Bouwen",L"Scène",L"Help",L"Taal",L"Nieuw",L"Open",L"Opslaan",L"Afsluiten",L"Uitvoeren",L"Engine bouwen",L"Pakket",L"Verkenner",L"Uitvoer",L"Gereed",L"Over",L"OK",L"Gestopt",L"Eerst bouwen"}},
|
||
{"uk","Українська",{L"Lity3D Редактор",L"Файл",L"Збірка",L"Сцена",L"Довідка",L"Мова",L"Новий",L"Відкрити",L"Зберегти",L"Вихід",L"Запуск",L"Зібрати",L"Упакувати",L"Провідник",L"Вивід",L"Готово",L"Про програму",L"OK",L"Зупинено",L"Спочатку зібрати"}},
|
||
{"cs","Čeština",{L"Lity3D Editor",L"Soubor",L"Sestavit",L"Scéna",L"Nápověda",L"Jazyk",L"Nový",L"Otevřít",L"Uložit",L"Konec",L"Spustit",L"Sestavit engine",L"Zabalit",L"Průzkumník",L"Výstup",L"Připraveno",L"O",L"OK",L"Zastaveno",L"Nejdřív sestavit"}},
|
||
{"ro","Română",{L"Lity3D Editor",L"Fișier",L"Compilă",L"Scenă",L"Ajutor",L"Limbă",L"Nou",L"Deschide",L"Salvează",L"Ieșire",L"Rulează",L"Compilează",L"Pachet",L"Explorator",L"Ieșire",L"Gata",L"Despre",L"OK",L"Oprit",L"Compilează prima"}},
|
||
{"sv","Svenska",{L"Lity3D Redigerare",L"Fil",L"Bygg",L"Scen",L"Hjälp",L"Språk",L"Ny",L"Öppna",L"Spara",L"Avsluta",L"Kör",L"Bygg engine",L"Paketera",L"Utforskare",L"Utdata",L"Redo",L"Om",L"OK",L"Stoppad",L"Bygg först"}},
|
||
{"fi","Suomi",{L"Lity3D Editor",L"Tiedosto",L"Käännä",L"Sken",L"Ohje",L"Kieli",L"Uusi",L"Avaa",L"Tallenna",L"Lopeta",L"Käynnistä",L"Käännä engine",L"Paketoi",L"Selain",L"Tuloste",L"Valmis",L"Tietoja",L"OK",L"Pysäytetty",L"Käännä ensin"}},
|
||
{"da","Dansk",{L"Lity3D Editor",L"Fil",L"Byg",L"Scene",L"Hjælp",L"Sprog",L"Ny",L"Åbn",L"Gem",L"Afslut",L"Kør",L"Byg engine",L"Pakke",L"Stifinder",L"Output",L"Klar",L"Om",L"OK",L"Stoppet",L"Byg først"}},
|
||
{"no","Norsk",{L"Lity3D Editor",L"Fil",L"Bygg",L"Scene",L"Hjelp",L"Språk",L"Ny",L"Åpne",L"Lagre",L"Avslutt",L"Kjør",L"Bygg engine",L"Pakke",L"Utforsker",L"Utdata",L"Klar",L"Om",L"OK",L"Stoppet",L"Bygg først"}},
|
||
{"el","Ελληνικά",{L"Lity3D Επεξεργαστής",L"Αρχείο",L"Κατασκευή",L"Σκηνή",L"Βοήθεια",L"Γλώσσα",L"Νέο",L"Άνοιγμα",L"Αποθήκευση",L"Έξοδος",L"Εκτέλεση",L"Κατασκευή",L"Πακέτο",L"Ανιχνευτής",L"Έξοδος",L"Έτοιμο",L"Σχετικά",L"OK",L"Σταμάτησε",L"Κατασκευή πρώτα"}},
|
||
{"he","עברית",{L"Lity3D עורך",L"קובץ",L"בנייה",L"סצנה",L"עזרה",L"שפה",L"חדש",L"פתח",L"שמור",L"יציאה",L"הרץ",L"בנה מנוע",L"ארוז",L"סייר",L"פלט",L"מוכן",L"אודות",L"אישור",L"נעצר",L"בנה קודם"}},
|
||
{"ms","Bahasa Melayu",{L"Lity3D Editor",L"Fail",L"Bina",L"Adegan",L"Bantuan",L"Bahasa",L"Baharu",L"Buka",L"Simpan",L"Keluar",L"Jalankan",L"Bina engine",L"Pakej",L"Peneroka",L"Output",L"Sedia",L"Tentang",L"OK",L"Dihentikan",L"Bina dahulu"}},
|
||
{"hu","Magyar",{L"Lity3D Szerkesztő",L"Fájl",L"Fordítás",L"Jelenet",L"Súgó",L"Nyelv",L"Új",L"Megnyitás",L"Mentés",L"Kilépés",L"Futtatás",L"Fordítás",L"Csomagolás",L"Fájlkezelő",L"Kimenet",L"Kész",L"Névjegy",L"OK",L"Leállítva",L"Előbb fordíts"}},
|
||
{"sk","Slovenčina",{L"Lity3D Editor",L"Súbor",L"Kompilácia",L"Scéna",L"Pomoc",L"Jazyk",L"Nový",L"Otvoriť",L"Uložiť",L"Ukončiť",L"Spustiť",L"Skompilovať",L"Balenie",L"Prieskumník",L"Výstup",L"Pripravené",L"O",L"OK",L"Zastavené",L"Skompilovať prvú"}},
|
||
{"bg","Български",{L"Lity3D Редактор",L"Файл",L"Компилация",L"Сцена",L"Помощ",L"Език",L"Нов",L"Отвори",L"Запази",L"Изход",L"Стартирай",L"Компилирай",L"Опаковай",L"Проводник",L"Изход",L"Готово",L"Относно",L"OK",L"Спряно",L"Първо компилирай"}},
|
||
{"hr","Hrvatski",{L"Lity3D Urednik",L"Datoteka",L"Izgradi",L"Scena",L"Pomoć",L"Jezik",L"Novo",L"Otvori",L"Spremi",L"Izlaz",L"Pokreni",L"Izgradi",L"Pakiraj",L"Istraživač",L"Izlaz",L"Spreman",L"O",L"OK",L"Zaustavljeno",L"Prvo izgradi"}},
|
||
{"sr","Српски",{L"Lity3D Уредник",L"Датотека",L"Изградња",L"Сцена",L"Помоћ",L"Језик",L"Ново",L"Отвори",L"Сачувај",L"Излаз",L"Покрени",L"Изгради",L"Пакуј",L"Истраживач",L"Излаз",L"Спреман",L"О",L"OK",L"Заустављено",L"Прво изгради"}},
|
||
{"sl","Slovenščina",{L"Lity3D Urejevalnik",L"Datoteka",L"Izgradi",L"Scena",L"Pomoč",L"Jezik",L"Novo",L"Odpri",L"Shrani",L"Izhod",L"Zaženi",L"Izgradi",L"Pakiraj",L"Raziskovalec",L"Izhod",L"Pripravljeno",L"O",L"OK",L"Ustavljeno",L"Najprej izgradi"}},
|
||
{"lt","Lietuvių",{L"Lity3D Redaktorius",L"Failas",L"Kompiliuoti",L"Scena",L"Pagalba",L"Kalba",L"Naujas",L"Atidaryti",L"Išsaugoti",L"Išeiti",L"Paleisti",L"Kompiliuoti",L"Pakuot",L"Naršyklė",L"Išvestis",L"Pasirengęs",L"Apie",L"OK",L"Sustabdyta",L"Kompiliuoti pirmiau"}},
|
||
{"lv","Latviešu",{L"Lity3D Redaktors",L"Fails",L"Kompilēt",L"Aina",L"Palīdzība",L"Valoda",L"Jauns",L"Atvērt",L"Saglabāt",L"Izeja",L"Palaist",L"Kompilēt",L"Pakēt",L"Pārlūks",L"Izeja",L"Gatavs",L"Par",L"OK",L"Aizturēts",L"Vispirums kompilēt"}},
|
||
{"et","Eesti",{L"Lity3D Redaktor",L"Fail",L"Kompileeri",L"Stseen",L"Abi",L"Keel",L"Uus",L"Ava",L"Salvesta",L"Välju",L"Käivita",L"Kompileeri",L"Pakendi",L"Eksploorija",L"Väljund",L"Valmis",L"Teave",L"OK",L"Peatatud",L"Esmalt kompileeri"}},
|
||
{"fa","فارسی",{L"Lity3D ویرایشگر",L"پرونده",L"ساخت",L"صحنه",L"راهنما",L"زبان",L"جدید",L"باز کردن",L"ذخیره",L"خروج",L"اجرا",L"ساخت موتور",L"بسته بندی",L"کاوشگر",L"خروجی",L"آماده",L"درباره",L"تأیید",L"متوقف شد",L"اول بساز"}},
|
||
{"bn","বাংলা",{L"Lity3D সম্পাদক",L"ফাইল",L"বিল্ড",L"দৃশ্য",L"সাহায্য",L"ভাষা",L"নতুন",L"খুলুন",L"সংরক্ষণ",L"বের হোন",L"চালান",L"ইঞ্জিন বিল্ড",L"EXE প্যাকেজ",L"এক্সপ্লোরার",L"আউটপুট",L"প্রস্তুত",L"সম্পর্কে",L"ঠিক আছে",L"বন্ধ",L"প্রথমে বিল্ড"}},
|
||
{"sw","Kiswahili",{L"Lity3D Mhariri",L"Faili",L"Jenga",L"Onyesho",L"Msaada",L"Lugha",L"Mpya",L"Fungua",L"Hifadhi",L"Ondoka",L"Endesha",L"Jenga injini",L"Pakiti",L"Vinara",L"Matokeo",L"Iko tayari",L"Kuhusu",L"Sawa",L"Imesimamishwa",L"Jenga kwanza"}},
|
||
{"ta","தமிழ்",{L"Lity3D திருத்தி",L"கோப்பு",L"உருவாக்கு",L"காட்சி",L"உதவி",L"மொழி",L"புதிய",L"திற",L"சேமி",L"வெளியேறு",L"இயக்கு",L"இயந்திரம் உருவாக்கு",L"EXE பேக்கேஜ்",L"ஆராய்ச்சியாளர்",L"வெளியீடு",L"தயார்",L"பற்றி",L"சரி",L"நிறுத்தப்பட்டது",L"முதலில் உருவாக்கு"}},
|
||
{"ml","മലയാളം",{L"Lity3D എഡിറ്റർ",L"ഫയൽ",L"ബിൽഡ്",L"രംഗം",L"സഹായം",L"ഭാഷ",L"പുതിയ",L"തുറക്കുക",L"സേവ് ചെയ്യുക",L"പുറത്തുപോകുക",L"റൺ ചെയ്യുക",L"എഞ്ചിൻ ബിൽഡ്",L"EXE പാക്കേജ്",L"എക്സ്പ്ലോറർ",L"ഔട്ട്പുട്ട്",L"തയ്യാർ",L"കുറിച്ച്",L"ശരി",L"നിർത്തി",L"ആദ്യം ബിൽഡ്"}},
|
||
{"te","తెలుగు",{L"Lity3D ఎడిటర్",L"ఫైల్",L"బిల్డ్",L"దృశ్యం",L"సహాయం",L"భాష",L"కొత్త",L"తెరవండి",L"సేవ్",L"నిష్క్రమించండి",L"రన్",L"ఇంజిన్ బిల్డ్",L"EXE ప్యాకేజ్",L"ఎక్స్ప్లోరర్",L"అవుట్పుట్",L"సిద్ధం",L"గురించి",L"సరే",L"ఆపబడింది",L"మొదట బిల్డ్"}},
|
||
{"ur","اردو",{L"Lity3D ایڈیٹر",L"فائل",L"بلڈ",L"منظر",L"مدد",L"زبان",L"نیا",L"کھولیں",L"محفوظ",L"باہر",L"چلائیں",L"اینجن بلڈ",L"EXE پیکج",L"ایکسپلورر",L"آؤٹ پٹ",L"تیار",L"بارے میں",L"ٹھیک ہے",L"روک دیا",L"پہلے بلڈ"}},
|
||
{"tl","Tagalog",{L"Lity3D Editor",L"File",L"Build",L"Scene",L"Tulong",L"Wika",L"Bago",L"Buksan",L"I-save",L"Lumabas",L"I-run",L"Build engine",L"Package",L"Explorer",L"Output",L"Handa",L"Tungkol",L"OK",L"Stopped",L"Build muna"}},
|
||
};
|
||
|
||
static int g_lang_count = NUM_LANGS;
|
||
static int g_cur = 0;
|
||
|
||
static const WCHAR* T(int k) {
|
||
if (k < NUM_KEYS && g_langs[g_cur].trans[k]) return g_langs[g_cur].trans[k];
|
||
return L"?";
|
||
}
|
||
|
||
static int detect_lang(void) {
|
||
WCHAR buf[10];
|
||
if (GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, buf, 10)) {
|
||
char abuf[16]; WideCharToMultiByte(CP_UTF8, 0, buf, -1, abuf, 16, NULL, NULL);
|
||
for (int i = 0; i < g_lang_count; i++)
|
||
if (!_stricmp(g_langs[i].code, abuf)) return i;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void populate_tree(void) {
|
||
TreeView_DeleteAllItems(g_tree);
|
||
TVINSERTSTRUCTW tvi = {0}; tvi.hParent = TVI_ROOT; tvi.hInsertAfter = TVI_LAST;
|
||
tvi.item.mask = TVIF_TEXT; tvi.item.pszText = L"lity3d";
|
||
HTREEITEM root = TreeView_InsertItem(g_tree, &tvi);
|
||
WIN32_FIND_DATAW fd; WCHAR pat[MAX_PATH];
|
||
wsprintfW(pat, L"%s\\*", g_engine_dir);
|
||
HANDLE hF = FindFirstFileW(pat, &fd);
|
||
if (hF == INVALID_HANDLE_VALUE) return;
|
||
do {
|
||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;
|
||
if (!wcscmp(fd.cFileName,L".")||!wcscmp(fd.cFileName,L"..")) continue;
|
||
if (!wcscmp(fd.cFileName,L".git")||!wcscmp(fd.cFileName,L"build")||!wcscmp(fd.cFileName,L"target")) continue;
|
||
tvi.hParent = root; tvi.item.pszText = fd.cFileName;
|
||
HTREEITEM d = TreeView_InsertItem(g_tree, &tvi);
|
||
WCHAR sub[MAX_PATH]; wsprintfW(sub, L"%s\\%s\\*", g_engine_dir, fd.cFileName);
|
||
WIN32_FIND_DATAW fd2; HANDLE h2 = FindFirstFileW(sub, &fd2);
|
||
if (h2 != INVALID_HANDLE_VALUE) {
|
||
do { if (fd2.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||
tvi.hParent = d; tvi.item.pszText = fd2.cFileName;
|
||
TreeView_InsertItem(g_tree, &tvi);
|
||
} while (FindNextFileW(h2, &fd2));
|
||
FindClose(h2);
|
||
}
|
||
} while (FindNextFileW(hF, &fd));
|
||
FindClose(hF);
|
||
}
|
||
|
||
static void open_file_at(WCHAR* path) {
|
||
HANDLE hf = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||
if (hf == INVALID_HANDLE_VALUE) return;
|
||
DWORD sz = GetFileSize(hf, NULL); char* buf = malloc(sz + 1); DWORD rd;
|
||
ReadFile(hf, buf, sz, &rd, NULL); buf[sz] = '\0'; CloseHandle(hf);
|
||
SetWindowTextA(g_edit, buf); free(buf);
|
||
wcscpy(g_current_file, path);
|
||
}
|
||
|
||
static void open_file_dialog(void) {
|
||
WCHAR file[MAX_PATH] = L""; OPENFILENAMEW of = {sizeof(of)};
|
||
of.lpstrFilter = L"All\0*.*\0Python\0*.py\0C\0*.c;*.h\0";
|
||
of.lpstrFile = file; of.nMaxFile = MAX_PATH; of.Flags = OFN_FILEMUSTEXIST;
|
||
if (GetOpenFileNameW(&of)) open_file_at(file);
|
||
}
|
||
|
||
static void save_file(void) {
|
||
if (!g_current_file[0]) { open_file_dialog(); return; }
|
||
int len = GetWindowTextLengthA(g_edit); char* buf = malloc(len + 1);
|
||
GetWindowTextA(g_edit, buf, len + 1);
|
||
HANDLE hf = CreateFileW(g_current_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||
if (hf != INVALID_HANDLE_VALUE) { DWORD wr; WriteFile(hf, buf, len, &wr, NULL); CloseHandle(hf); }
|
||
free(buf);
|
||
}
|
||
|
||
static void console_msg(const char* msg) {
|
||
int len = GetWindowTextLengthA(g_console);
|
||
SendMessageA(g_console, EM_SETSEL, len, len);
|
||
SendMessageA(g_console, EM_REPLACESEL, FALSE, (LPARAM)msg);
|
||
}
|
||
|
||
static void rebuild_lang_menu(void) {
|
||
HMENU hBar = GetMenu(g_hwnd);
|
||
HMENU hOld = GetSubMenu(hBar, 3);
|
||
HMENU hLang = CreatePopupMenu();
|
||
for (int i = 0; i < g_lang_count; i++) {
|
||
WCHAR label[192];
|
||
wsprintfW(label, L"%hs (%hs)", g_langs[i].name, g_langs[i].code);
|
||
UINT flags = (i == g_cur) ? (MF_STRING | MF_CHECKED) : MF_STRING;
|
||
AppendMenuW(hLang, flags, IDM_LANG_BASE + i, label);
|
||
}
|
||
RemoveMenu(hBar, 3, MF_BYPOSITION);
|
||
InsertMenuW(hBar, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hLang, L"语言");
|
||
if (hOld) DestroyMenu(hOld);
|
||
DrawMenuBar(g_hwnd);
|
||
}
|
||
|
||
static LRESULT CALLBACK WP(HWND h, UINT m, WPARAM w, LPARAM l) {
|
||
switch (m) {
|
||
case WM_COMMAND: {
|
||
int id = LOWORD(w);
|
||
if (id == IDM_NEW) { SetWindowTextA(g_edit, ""); g_current_file[0] = 0; }
|
||
else if (id == IDM_OPEN) open_file_dialog();
|
||
else if (id == IDM_SAVE) save_file();
|
||
else if (id == IDM_RUN) {
|
||
WCHAR p[MAX_PATH]; wsprintfW(p, L"%s\\build\\lity.exe", g_engine_dir);
|
||
if (GetFileAttributesW(p) == INVALID_FILE_ATTRIBUTES) { console_msg("[!] Build first\n"); return 0; }
|
||
ShellExecuteW(NULL, L"open", p, NULL, g_engine_dir, SW_SHOWNORMAL);
|
||
}
|
||
else if (id == IDM_BUILD) {
|
||
WCHAR cmd[MAX_PATH*2]; wsprintfW(cmd, L"/c set PATH=C:\\mingw64\\bin;%%PATH%%&& cd /d %s\\build && cmake --build . -j4", g_engine_dir);
|
||
ShellExecuteW(NULL, L"open", L"cmd.exe", cmd, NULL, SW_SHOWNORMAL);
|
||
}
|
||
else if (id == IDM_ABOUT) MessageBoxW(h, L"Lity3D Engine v1.0", L"About", MB_OK);
|
||
else if (id >= IDM_LANG_BASE && id < IDM_LANG_BASE + g_lang_count) {
|
||
g_cur = id - IDM_LANG_BASE;
|
||
SetWindowTextW(g_hwnd, T(0));
|
||
rebuild_lang_menu();
|
||
populate_tree();
|
||
// Rebuild ALL menus with new language
|
||
HMENU hBar = GetMenu(g_hwnd);
|
||
HMENU hFile = CreatePopupMenu();
|
||
AppendMenuW(hFile, MF_STRING, IDM_NEW, T(6));
|
||
AppendMenuW(hFile, MF_STRING, IDM_OPEN, T(7));
|
||
AppendMenuW(hFile, MF_STRING, IDM_SAVE, T(8));
|
||
AppendMenuW(hFile, MF_SEPARATOR, 0, NULL);
|
||
AppendMenuW(hFile, MF_STRING, IDM_ABOUT, T(16));
|
||
RemoveMenu(hBar, 0, MF_BYPOSITION);
|
||
InsertMenuW(hBar, 0, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hFile, T(1));
|
||
DestroyMenu(GetSubMenu(hBar, 1)); // old build menu gone after insert
|
||
// Rebuild build menu
|
||
HMENU hBuild = CreatePopupMenu();
|
||
AppendMenuW(hBuild, MF_STRING, IDM_RUN, T(10));
|
||
AppendMenuW(hBuild, MF_SEPARATOR, 0, NULL);
|
||
AppendMenuW(hBuild, MF_STRING, IDM_BUILD, T(11));
|
||
AppendMenuW(hBuild, MF_STRING, IDM_PACKAGE, T(12));
|
||
RemoveMenu(hBar, 1, MF_BYPOSITION);
|
||
InsertMenuW(hBar, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hBuild, T(2));
|
||
DestroyMenu(GetSubMenu(hBar, 3)); // old help
|
||
// Rebuild help menu
|
||
HMENU hHelp = CreatePopupMenu();
|
||
AppendMenuW(hHelp, MF_STRING, IDM_ABOUT, T(16));
|
||
RemoveMenu(hBar, 3, MF_BYPOSITION);
|
||
InsertMenuW(hBar, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hHelp, T(4));
|
||
DrawMenuBar(g_hwnd);
|
||
}
|
||
break; }
|
||
case WM_NOTIFY: {
|
||
NMHDR* nm = (NMHDR*)l;
|
||
if (nm->idFrom == IDC_TREE && nm->code == TVN_SELCHANGED) {
|
||
TVITEMW ti = {0}; ti.mask = TVIF_TEXT | TVIF_HANDLE;
|
||
ti.hItem = TreeView_GetSelection(g_tree);
|
||
WCHAR name[MAX_PATH]; ti.pszText = name; ti.cchTextMax = MAX_PATH;
|
||
TreeView_GetItem(g_tree, &ti);
|
||
if (!ti.hItem) break;
|
||
HTREEITEM par = TreeView_GetParent(g_tree, ti.hItem);
|
||
WCHAR full[MAX_PATH];
|
||
if (par) { WCHAR parent[MAX_PATH]={0}; TVITEMW pti={0};
|
||
pti.mask=TVIF_TEXT; pti.hItem=par; pti.pszText=parent; pti.cchTextMax=MAX_PATH;
|
||
TreeView_GetItem(g_tree, &pti);
|
||
wsprintfW(full, L"%s\\%s\\%s", g_engine_dir, parent, name);
|
||
} else wsprintfW(full, L"%s\\%s", g_engine_dir, name);
|
||
DWORD attr = GetFileAttributesW(full);
|
||
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
|
||
open_file_at(full);
|
||
}
|
||
break; }
|
||
case WM_SIZE: {
|
||
int w2 = LOWORD(l), h2 = HIWORD(l);
|
||
if (w2<100||h2<100) break;
|
||
int tw=220, ch=160;
|
||
MoveWindow(g_tree,0,0,tw,h2-ch,TRUE);
|
||
MoveWindow(g_edit,tw+4,0,w2-tw-4,h2-ch,TRUE);
|
||
MoveWindow(g_console,0,h2-ch,w2,ch-24,TRUE);
|
||
break; }
|
||
case WM_DESTROY: PostQuitMessage(0); return 0;
|
||
}
|
||
return DefWindowProcW(h, m, w, l);
|
||
}
|
||
|
||
int WINAPI wWinMain(HINSTANCE hI, HINSTANCE hP, LPWSTR nC, int nS) {
|
||
(void)hP; (void)nC; (void)nS;
|
||
GetModuleFileNameW(NULL, g_engine_dir, MAX_PATH);
|
||
WCHAR* sl = wcsrchr(g_engine_dir, L'\\'); if (sl) *sl = 0;
|
||
sl = wcsrchr(g_engine_dir, L'\\'); if (sl) *sl = 0;
|
||
INITCOMMONCONTROLSEX icc = {sizeof(icc), ICC_TREEVIEW_CLASSES}; InitCommonControlsEx(&icc);
|
||
g_cur = detect_lang();
|
||
WNDCLASSEXW wc = {sizeof(wc)}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WP;
|
||
wc.hInstance = hI; wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
||
wc.lpszClassName = L"LityEditor"; wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
RegisterClassExW(&wc);
|
||
g_hwnd = CreateWindowExW(0, L"LityEditor", T(0), WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN, 100,100,1400,900, NULL, NULL, hI, NULL);
|
||
g_tree = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, L"", WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT, 0,0,220,600, g_hwnd, (HMENU)IDC_TREE, hI, NULL);
|
||
g_edit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOVSCROLL, 224,0,1176,600, g_hwnd, (HMENU)IDC_EDIT, hI, NULL);
|
||
SendMessageW(g_edit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);
|
||
g_console = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_MULTILINE|ES_READONLY, 0,600,1400,136, g_hwnd, (HMENU)IDC_CONSOLE, hI, NULL);
|
||
HFONT hf = CreateFontW(14,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,0,0,0,FIXED_PITCH,L"Consolas");
|
||
SendMessageW(g_console, WM_SETFONT, (WPARAM)hf, TRUE);
|
||
HMENU hBar = CreateMenu();
|
||
HMENU hFile = CreatePopupMenu();
|
||
AppendMenuW(hFile,MF_STRING,IDM_NEW,T(6)); AppendMenuW(hFile,MF_STRING,IDM_OPEN,T(7));
|
||
AppendMenuW(hFile,MF_STRING,IDM_SAVE,T(8)); AppendMenuW(hFile,MF_SEPARATOR,0,NULL);
|
||
AppendMenuW(hFile,MF_STRING,IDM_ABOUT,T(16));
|
||
AppendMenuW(hBar,MF_POPUP,(UINT_PTR)hFile,T(1));
|
||
HMENU hBuild = CreatePopupMenu();
|
||
AppendMenuW(hBuild,MF_STRING,IDM_RUN,T(10)); AppendMenuW(hBuild,MF_SEPARATOR,0,NULL);
|
||
AppendMenuW(hBuild,MF_STRING,IDM_BUILD,T(11)); AppendMenuW(hBuild,MF_STRING,IDM_PACKAGE,T(12));
|
||
AppendMenuW(hBar,MF_POPUP,(UINT_PTR)hBuild,T(2));
|
||
HMENU hLang = CreatePopupMenu();
|
||
for (int i = 0; i < g_lang_count; i++) {
|
||
WCHAR label[192]; wsprintfW(label, L"%hs (%hs)", g_langs[i].name, g_langs[i].code);
|
||
UINT flags = (i == g_cur) ? (MF_STRING|MF_CHECKED) : MF_STRING;
|
||
AppendMenuW(hLang, flags, IDM_LANG_BASE + i, label);
|
||
}
|
||
AppendMenuW(hBar,MF_POPUP,(UINT_PTR)hLang,T(5));
|
||
HMENU hHelp = CreatePopupMenu();
|
||
AppendMenuW(hHelp,MF_STRING,IDM_ABOUT,T(16));
|
||
AppendMenuW(hBar,MF_POPUP,(UINT_PTR)hHelp,T(4));
|
||
SetMenu(g_hwnd,hBar);
|
||
populate_tree();
|
||
console_msg("Lity3D Editor ready.\n");
|
||
ShowWindow(g_hwnd,SW_SHOW);
|
||
MSG msg;
|
||
while(GetMessageW(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessageW(&msg);}
|
||
return (int)msg.wParam;
|
||
}
|