Skip to content

Commit 643946c

Browse files
Initial commit: SexyUI Editor v1.0
A visual UI editor for the Sexy framework used in Plants vs. Zombies. Supports both C++ and C# (.NET) code generation. Features: - Visual drag-and-drop interface design - Dual platform support (C++ and C#) - Resource management with preview - Code generation with user code preservation - Extension component system - Internationalization (English/Chinese) - Event system with predefined actions - Atlas image support for .NET version
0 parents  commit 643946c

61 files changed

Lines changed: 12410 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[codz]
4+
*$py.class
5+
*.pyc
6+
*.pyo
7+
*.pyd
8+
9+
# C extensions
10+
*.so
11+
12+
# Distribution / packaging
13+
.Python
14+
build/
15+
develop-eggs/
16+
dist/
17+
downloads/
18+
eggs/
19+
.eggs/
20+
lib/
21+
lib64/
22+
parts/
23+
sdist/
24+
var/
25+
wheels/
26+
share/python-wheels/
27+
*.egg-info/
28+
.installed.cfg
29+
*.egg
30+
MANIFEST
31+
32+
# PyInstaller
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py.cover
51+
.hypothesis/
52+
.pytest_cache/
53+
cover/
54+
55+
# Translations
56+
*.mo
57+
*.pot
58+
59+
# Django stuff:
60+
*.log
61+
local_settings.py
62+
db.sqlite3
63+
db.sqlite3-journal
64+
65+
# Flask stuff:
66+
instance/
67+
.webassets-cache
68+
69+
# Scrapy stuff:
70+
.scrapy
71+
72+
# Sphinx documentation
73+
docs/_build/
74+
75+
# PyBuilder
76+
.pybuilder/
77+
target/
78+
79+
# Jupyter Notebook
80+
.ipynb_checkpoints
81+
82+
# IPython
83+
profile_default/
84+
ipython_config.py
85+
86+
# Environments
87+
.env
88+
.envrc
89+
.venv
90+
env/
91+
venv/
92+
ENV/
93+
env.bak/
94+
venv.bak/
95+
96+
# IDE
97+
.idea/
98+
.vscode/
99+
*.swp
100+
*.swo
101+
102+
# mypy
103+
.mypy_cache/
104+
.dmypy.json
105+
dmypy.json
106+
107+
# Pyre type checker
108+
.pyre/
109+
110+
# pytype static type analyzer
111+
.pytype/
112+
113+
# Cython debug symbols
114+
cython_debug/
115+
116+
# Ruff stuff:
117+
.ruff_cache/
118+
119+
# PyPI configuration file
120+
.pypirc
121+
122+
# Project specific
123+
*.sexyui
124+
*.cssexyui
125+
126+
# Resource files (too large)
127+
pak/
128+
Content/
129+
130+
# OS files
131+
.DS_Store
132+
Thumbs.db

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 StackAndPointer
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# SexyUI Editor
2+
3+
A visual UI editor for the Sexy framework used in Plants vs. Zombies, supporting both C++ and C# (.NET) code generation.
4+
5+
![License](https://img.shields.io/badge/license-MIT-blue.svg)
6+
![Platform](https://img.shields.io/badge/platform-Windows-lightgrey.svg)
7+
![Python](https://img.shields.io/badge/python-3.8%2B-green.svg)
8+
9+
## Features
10+
11+
- 🎨 **Visual Design**: Drag-and-drop interface for UI layout design
12+
- 🔄 **Dual Platform Support**: Generate code for both C++ and C# (.NET) versions
13+
- 🖼️ **Resource Management**: Built-in image and font resource browser with preview
14+
- 📝 **Code Generation**: Automatic code generation with user code preservation
15+
- 🔌 **Extension System**: Support for custom extension components
16+
- 🌍 **Internationalization**: Multi-language support (English/Chinese)
17+
- 🎯 **Event System**: Visual event configuration with predefined actions
18+
- 📦 **Atlas Support**: Automatic Atlas sub-image detection and preview for .NET version
19+
20+
## Screenshots
21+
22+
![Main Interface](docs/screenshots/main_interface.png)
23+
24+
## Getting Started
25+
26+
### Prerequisites
27+
28+
- Python 3.8 or higher
29+
- PyQt6
30+
- Windows OS (tested on Windows 10/11)
31+
32+
### Installation
33+
34+
1. Clone the repository:
35+
```bash
36+
git clone https://github.com/yourusername/SexyUIEditor.git
37+
cd SexyUIEditor
38+
```
39+
40+
2. Install dependencies:
41+
```bash
42+
pip install PyQt6
43+
```
44+
45+
3. Run the editor:
46+
```bash
47+
python main.py
48+
```
49+
50+
## Usage
51+
52+
### Creating a New Project
53+
54+
1. Click **File → New** or press `Ctrl+N`
55+
2. Select target platform (C++ or C#)
56+
3. Design your interface using the component toolbox
57+
4. Configure widget properties in the property panel
58+
5. Save the project with `.sexyui` (C++) or `.cssexyui` (C#) extension
59+
60+
### Designing Interfaces
61+
62+
- **Add Widgets**: Drag components from the toolbox to the canvas
63+
- **Select Widgets**: Click on widgets to select them
64+
- **Move Widgets**: Drag selected widgets to reposition
65+
- **Resize Widgets**: Use the resize handles on selected widgets
66+
- **Delete Widgets**: Press `Delete` key or use Edit menu
67+
68+
### Code Generation
69+
70+
1. Press `F6` or click **View → View Code** to preview generated code
71+
2. Click **View → Export All Interfaces...** to export all interfaces
72+
3. Generated code preserves user modifications in marked regions
73+
74+
### Event Configuration
75+
76+
1. Select a widget in the object tree or canvas
77+
2. Click the event button in the property panel
78+
3. Add predefined actions or write custom code
79+
4. User code is preserved in `// [[[HANDLER_xxx]]]` regions
80+
81+
## Project Structure
82+
83+
```
84+
SexyUIEditor/
85+
├── core/ # Core business logic
86+
│ ├── generators/ # Code generation modules
87+
│ ├── component_registry.py # Widget definitions
88+
│ ├── extension_manager.py # Extension component management
89+
│ └── i18n.py # Internationalization
90+
├── ui/ # User interface components
91+
├── Content/ # .NET game resources
92+
├── SexyUIExtensions/ # Extension components
93+
├── docs/ # Documentation
94+
└── main.py # Application entry point
95+
```
96+
97+
## Supported Widgets
98+
99+
### Basic Widgets
100+
- ButtonWidget - Basic button
101+
- EditWidget - Text input
102+
- Checkbox - Checkbox control
103+
- Slider - Slider control
104+
- Dialog - Dialog window
105+
- ListWidget - Scrollable list
106+
107+
### PVZ Widgets
108+
- LawnStoneButton - PVZ stone-style button
109+
- NewLawnButton - PVZ new-style button
110+
- LawnDialog - PVZ dialog
111+
- LawnEditWidget - PVZ edit control
112+
- GameButton - PVZ game button
113+
114+
### Extension Widgets
115+
- Label - Custom text label with auto-wrapping
116+
- ImageBox - Custom image box with scaling support
117+
118+
## Extension System
119+
120+
Create custom widgets by adding JSON definitions and source files to the `SexyUIExtensions/` directory:
121+
122+
```
123+
SexyUIExtensions/
124+
├── cpp/
125+
│ ├── MyWidget.json
126+
│ ├── MyWidget.h
127+
│ └── MyWidget.cpp
128+
└── csharp/
129+
├── MyWidget.json
130+
└── MyWidget.cs
131+
```
132+
133+
See [CORE_ARCHITECTURE_EN.md](docs/CORE_ARCHITECTURE_EN.md) for details.
134+
135+
## Building
136+
137+
Use the provided build script to create a standalone executable:
138+
139+
```batch
140+
build.bat
141+
```
142+
143+
This creates a standalone executable in `dist/main.dist/` with all dependencies included.
144+
145+
## Contributing
146+
147+
We welcome contributions! Here are some areas where you can help:
148+
149+
### Code Output Formats
150+
- **More C++ formats**: Support for different C++ coding styles and frameworks
151+
- **Assembly output**: Add support for generating assembly code for low-level optimizations
152+
- **Other languages**: Extend to support additional programming languages
153+
154+
### How to Contribute
155+
1. Fork the repository
156+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
157+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
158+
4. Push to the branch (`git push origin feature/amazing-feature`)
159+
5. Open a Pull Request
160+
161+
Please read [CORE_ARCHITECTURE_EN.md](docs/CORE_ARCHITECTURE_EN.md) for architecture details before contributing.
162+
163+
## Acknowledgments
164+
165+
Special thanks to **PopCap Games** for open-sourcing the **Sexy framework**, which made this editor possible. The Sexy framework is a lightweight, efficient UI framework that powers Plants vs. Zombies and other PopCap games.
166+
167+
## License
168+
169+
Copyright (C) 2026 StackAndPointer
170+
171+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
172+
173+
## Documentation
174+
175+
- [Core Architecture (Chinese)](docs/CORE_ARCHITECTURE.md)
176+
- [Core Architecture (English)](docs/CORE_ARCHITECTURE_EN.md)
177+
178+
## Support
179+
180+
If you encounter any issues or have questions, please [open an issue](https://github.com/yourusername/SexyUIEditor/issues) on GitHub.
181+
182+
---
183+
184+
**Note**: This editor is designed for the Sexy framework used in Plants vs. Zombies. Make sure you have the appropriate game resources and source code to use the generated code effectively.

SexyUIExtensions/cpp/ImageBox.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"class_name": "ImageBox",
3+
"display_name": "图片框",
4+
"description": "图片显示框(使用TodDrawImageScaledF绘制)",
5+
"parent_class": "",
6+
"is_container": false,
7+
"properties": [
8+
{"name": "mX", "prop_type": "int", "default": 0, "display_name": "X坐标", "category": "geometry", "tooltip": "图片框左上角的X坐标"},
9+
{"name": "mY", "prop_type": "int", "default": 0, "display_name": "Y坐标", "category": "geometry", "tooltip": "图片框左上角的Y坐标"},
10+
{"name": "mWidth", "prop_type": "int", "default": 100, "display_name": "宽度", "category": "geometry", "tooltip": "图片框的宽度"},
11+
{"name": "mHeight", "prop_type": "int", "default": 100, "display_name": "高度", "category": "geometry", "tooltip": "图片框的高度"},
12+
{"name": "mImage", "prop_type": "image", "default": "", "display_name": "图片", "category": "content", "tooltip": "显示的图片资源"},
13+
{"name": "mScaleX", "prop_type": "float", "default": 1.0, "display_name": "X缩放", "category": "appearance", "tooltip": "X方向缩放比例"},
14+
{"name": "mScaleY", "prop_type": "float", "default": 1.0, "display_name": "Y缩放", "category": "appearance", "tooltip": "Y方向缩放比例"},
15+
{"name": "mStretch", "prop_type": "bool", "default": false, "display_name": "拉伸填充", "category": "appearance", "tooltip": "是否拉伸图片填充整个区域"}
16+
],
17+
"source_code": "// ImageBox.cpp - Custom ImageBox Widget\n#include \"ImageBox.h\"\n#include \"TodCommon.h\"\n#include \"TodGraphics.h\"\n\nImageBox::ImageBox()\n{\n mX = 0;\n mY = 0;\n mWidth = 100;\n mHeight = 100;\n mImage = nullptr;\n mScaleX = 1.0f;\n mScaleY = 1.0f;\n mStretch = false;\n}\n\nvoid ImageBox::Draw(Graphics* g)\n{\n if (mImage != nullptr)\n {\n if (mStretch)\n {\n float scaleX = (float)mWidth / mImage->GetWidth();\n float scaleY = (float)mHeight / mImage->GetHeight();\n TodDrawImageScaledF(g, mImage, (float)mX, (float)mY, scaleX, scaleY);\n }\n else\n {\n TodDrawImageScaledF(g, mImage, (float)mX, (float)mY, mScaleX, mScaleY);\n }\n }\n}\n",
18+
"header_code": "// ImageBox.h - Custom ImageBox Widget\n#pragma once\n\n#include \"Widget.h\"\n#include \"Graphics.h\"\n#include \"Image.h\"\n\nclass ImageBox : public Widget\n{\npublic:\n ImageBox();\n virtual ~ImageBox() {}\n \n virtual void Draw(Graphics* g) override;\n \n // Properties\n int mX;\n int mY;\n int mWidth;\n int mHeight;\n Image* mImage;\n float mScaleX;\n float mScaleY;\n bool mStretch;\n};\n",
19+
"platform": "cpp"
20+
}

SexyUIExtensions/cpp/Label.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"class_name": "Label",
3+
"display_name": "文本标签",
4+
"description": "文本标签(使用TodDrawString绘制)",
5+
"parent_class": "",
6+
"is_container": false,
7+
"properties": [
8+
{"name": "mX", "prop_type": "int", "default": 0, "display_name": "X坐标", "category": "geometry", "tooltip": "标签左上角的X坐标"},
9+
{"name": "mY", "prop_type": "int", "default": 0, "display_name": "Y坐标", "category": "geometry", "tooltip": "标签左上角的Y坐标"},
10+
{"name": "mWidth", "prop_type": "int", "default": 100, "display_name": "宽度", "category": "geometry", "tooltip": "标签的宽度"},
11+
{"name": "mHeight", "prop_type": "int", "default": 30, "display_name": "高度", "category": "geometry", "tooltip": "标签的高度"},
12+
{"name": "mText", "prop_type": "string", "default": "", "display_name": "文本内容", "category": "content", "tooltip": "显示的文本"},
13+
{"name": "mFont", "prop_type": "font", "default": "FONT_DWARVENTODCRAFT12", "display_name": "字体", "category": "content", "tooltip": "文本使用的字体"},
14+
{"name": "mColor", "prop_type": "color", "default": "255,255,255", "display_name": "颜色", "category": "appearance", "tooltip": "文本颜色"},
15+
{"name": "mJustify", "prop_type": "enum", "default": "LEFT", "display_name": "对齐方式", "enum_values": ["LEFT", "CENTER", "RIGHT"], "category": "content", "tooltip": "文本对齐方式"}
16+
],
17+
"source_code": "// Label.cpp - Custom Label Widget\n#include \"Label.h\"\n\nLabel::Label()\n{\n mX = 0;\n mY = 0;\n mWidth = 100;\n mHeight = 30;\n mText = \"\";\n mFont = Font::FONT_DWARVENTODCRAFT12;\n mColor = Color(255, 255, 255);\n mJustify = Justification::LEFT;\n}\n\nvoid Label::Draw(Graphics* g)\n{\n if (!mText.empty())\n {\n g->SetFont(mFont);\n g->SetColor(mColor);\n g->DrawString(mText, mX, mY, mWidth, mHeight, mJustify);\n }\n}\n",
18+
"header_code": "// Label.h - Custom Label Widget\n#pragma once\n\n#include \"Widget.h\"\n#include \"Graphics.h\"\n#include \"Font.h\"\n#include \"Color.h\"\n\nclass Label : public Widget\n{\npublic:\n Label();\n virtual ~Label() {}\n \n virtual void Draw(Graphics* g) override;\n \n // Properties\n int mX;\n int mY;\n int mWidth;\n int mHeight;\n std::string mText;\n Font* mFont;\n Color mColor;\n Justification mJustify;\n};\n",
19+
"platform": "cpp"
20+
}

0 commit comments

Comments
 (0)