File size: 5,996 Bytes
41d6e2b
 
dddf9a7
 
 
 
 
 
 
 
 
 
3c38be2
dddf9a7
3c38be2
dddf9a7
3c38be2
dddf9a7
 
 
3c38be2
 
 
 
 
 
 
 
 
 
 
 
 
dddf9a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41d6e2b
dddf9a7
 
 
89f261c
 
 
 
 
 
 
41d6e2b
dddf9a7
 
 
 
 
 
 
 
89f261c
dddf9a7
 
 
 
 
 
 
 
 
 
 
41d6e2b
dddf9a7
 
41d6e2b
dddf9a7
 
 
41d6e2b
dddf9a7
 
 
41d6e2b
dddf9a7
41d6e2b
dddf9a7
 
 
66f12a9
 
dddf9a7
41d6e2b
dddf9a7
 
 
 
 
3c38be2
89f261c
dddf9a7
41d6e2b
 
3c38be2
 
 
41d6e2b
 
dddf9a7
 
 
 
 
 
 
 
 
 
 
3c38be2
dddf9a7
 
 
3c38be2
 
 
dddf9a7
 
89f261c
dddf9a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41d6e2b
3c38be2
 
 
 
 
 
 
 
dddf9a7
 
41d6e2b
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import gradio as gr
from pathlib import Path
import sys

# Paths
PROJECT_ROOT = Path(__file__).resolve().parent
GENERATED_SCRIPT_PATH = PROJECT_ROOT / "generated" / "result_script.py"

# Add root to sys.path so we can import process.py from app/
sys.path.insert(0, str(PROJECT_ROOT / "app"))

from app.process import main as generate_from_llm  # This runs generation
from src.llm_client import reset_memory  # ✅ Import reset function for new part

def generate_new_part(description):
    """
    Generates a completely new FreeCAD script (resets memory) and returns:
    - The script text for preview
    - The file path for download
    """
    reset_memory()  # ✅ Start fresh for a new part
    return _generate_script(description)

def edit_existing_part(description):
    """
    Edits the existing FreeCAD script using conversation context and returns:
    - The updated script text for preview
    - The file path for download
    """
    return _generate_script(description)

def _generate_script(description):
    """Helper to call process.py with given description."""
    import builtins
    original_input = builtins.input
    builtins.input = lambda _: description
    try:
        generate_from_llm()
    finally:
        builtins.input = original_input

    if GENERATED_SCRIPT_PATH.exists():
        script_text = GENERATED_SCRIPT_PATH.read_text(encoding="utf-8")
        return script_text, str(GENERATED_SCRIPT_PATH)
    else:
        return "Error: Script was not generated.", None


css = """
    body { background-color: #202020; color: white; margin: 0; padding: 0; }
    .gradio-container {
        max-width: 1400px;
        width: 95vw;
        margin: auto;
    }
    .title { text-align: center; font-size: 2.5em; margin-bottom: 0.1em; }
    .description { text-align: center; font-size: 1.1em; margin-bottom: 1em; color: #ccc; }
    .preview-box { 
        max-height: 400px;
        background-color: #111;
        border: 1px solid #444;
        padding: 10px;
        font-family: monospace;
        white-space: pre-wrap;
        color: #0f0;
    }
    .download-container {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5em;
        padding-left: 15px;
        height: 400px;
        justify-content: flex-start;
        width: 500px;
    }
    .download-button { width: 100%; }
    .instructions {
        font-size: 0.9em; color: #aaa;
        max-width: 300px;
        white-space: pre-line;
    }
    .footer { 
        margin-top: 2em; 
        text-align: center; 
        font-size: 0.9em; 
        color: #888;
        border-top: 1px solid #444;
        padding-top: 1em;
    }
    .footer a { color: #6af; text-decoration: none; }
    .footer a:hover { text-decoration: underline; }
"""

# Description 
cadomatic_description_md = """ 
<div style="text-align: center;">

Seamlessly creating python scripts for FreeCAD — from prompt to model.

CADomatic is a Python-powered tool that transforms prompts into **editable** parametric CAD scripts for FreeCAD. Rather than static models, it generates fully customizable Python code that programmatically builds CAD geometry — enabling engineers to define parts, reuse templates, and iterate rapidly.<br>
CADomatic primarily aims at **reducing product development time** by making a base design which can be modified to suit the designer's main goal.<br>
CADomatic creates native FreeCAD Python scripts for simple parts **with a complete design tree**.<br>
 <br>
Explore [CADomatic on GitHub](https://github.com/yas1nsyed/CADomatic) and if you find it useful, please ⭐ star the repository!
"""

with gr.Blocks(css=css) as demo:
    gr.Markdown("<div class='title'>CADomatic - AI powered CAD design generator</div>") # Title
    gr.Markdown(cadomatic_description_md)

    description_input = gr.Textbox(
        label="Describe your desired CAD model or modification below:",
        lines=2,
        placeholder="e.g., Create a flange with OD 100mm, bore size 50mm and 6 m8 holes at PCD 75mm..."
    )

    with gr.Row():
        generate_new_btn = gr.Button("Generate New Part", variant="primary")
        edit_existing_btn = gr.Button("Edit Existing Part", variant="secondary")

    with gr.Row():
        with gr.Column(scale=1):
            preview_output = gr.Code(
                label="Generated Script Preview",
                language="python",
                elem_classes="preview-box"
            )
            download_btn = gr.DownloadButton(
                label="Download Python Script",
                elem_classes="download-button"
            )
        with gr.Column(scale=1):
            gr.Markdown( 
                """
                <div class='instructions'>
                <b>Instructions:</b><br>
                - Enter the description for your desired CAD part or an edit instruction.<br>
                - Click on "Generate New Part" to start fresh.<br>
                - Click on "Edit Existing Part" to modify the last script.<br>
                - Preview the generated Python code.<br>
                - Paste the generated code into the python console of your FreeCAD app.<br>
                - (or)<br> 
                - Download the script.<br>
                - In your FreeCAD python console, paste - exec(open(r"path to your python script").read())
                </div>
                """
            )

    # Footer
    gr.Markdown( 
        """
        <div class='footer'>
        CADomatic is still under development and may sometimes produce inaccurate results.<br>
         <br>
        Made with ❤️ by Yasin
        </div>
        """
    )

    generate_new_btn.click(
        fn=generate_new_part,
        inputs=description_input,
        outputs=[preview_output, download_btn]
    )

    edit_existing_btn.click(
        fn=edit_existing_part,
        inputs=description_input,
        outputs=[preview_output, download_btn]
    )

if __name__ == "__main__":
    demo.launch()