awacke1 commited on
Commit
d88550f
·
verified ·
1 Parent(s): 5f40a57

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -79
app.py CHANGED
@@ -4,106 +4,140 @@ import random
4
 
5
  @st.cache_data
6
  def scan_assets():
7
- """Finds all textures, bump maps, and 3D models in the current folder."""
8
- img_exts = (".jpg", ".jpeg", ".png", ".gif")
9
  files = [f for f in os.listdir() if os.path.isfile(f)]
 
 
 
10
  textures = [
11
  f for f in files
12
  if f.lower().endswith(img_exts)
13
  and not any(tag in f.lower() for tag in ("bump", "normal"))
14
  ]
 
 
15
  bump_maps = [
16
  f for f in files
17
  if f.lower().endswith(img_exts)
18
  and any(tag in f.lower() for tag in ("bump", "normal"))
19
  ]
20
- model_files = [
21
- f for f in files
22
- if f.lower().endswith((".glb", ".gltf", ".obj"))
23
- ]
24
- return textures, bump_maps, model_files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  def main():
27
- st.title("🔳 A-Frame Tilemap with Mixed 3D Models")
28
- grid_size = st.sidebar.slider("Grid Size", min_value=1, max_value=20, value=10)
29
- textures, bump_maps, model_files = scan_assets()
30
 
31
- if not textures or not model_files:
32
- st.warning("⚠️ Add at least one texture **and** one `.glb`/`.obj` file to this folder.")
 
33
  return
34
 
35
- # --- Build <a-assets> entries ---
36
  asset_tags = []
37
  for i, tex in enumerate(textures):
38
  asset_tags.append(f'<img id="tex{i}" src="{tex}">')
 
39
  if bump_maps:
40
- asset_tags.append(f'<img id="grassBump" src="{bump_maps[0]}">')
41
- models_info = []
42
- for i, fname in enumerate(model_files):
43
- ext = os.path.splitext(fname)[1].lower()
44
- # strip the dot for ID
45
- asset_tags.append(f'<a-asset-item id="model{i}" src="{fname}"></a-asset-item>')
46
- models_info.append({"id": f"#model{i}", "ext": ext})
 
 
47
 
48
  assets_html = "\n ".join(asset_tags)
49
- texture_list = ", ".join(f'"#tex{i}"' for i in range(len(textures)))
50
- # JS array of model objects
51
- model_js_array = ", ".join(
52
- f'{{id:"{m["id"]}", ext:"{m["ext"]}"}}' for m in models_info
53
- )
54
 
55
- # ground material JS
 
 
 
 
 
 
 
 
 
 
 
 
56
  if bump_maps:
57
- ground_mat = (
58
- "ground.setAttribute('material',"
59
- "'color: #228B22; bumpMap: #grassBump; bumpScale: 0.2');"
60
- )
61
  else:
62
- ground_mat = "ground.setAttribute('material','color: #228B22');"
63
 
 
64
  html = f"""
65
- <!DOCTYPE html>
66
- <html>
67
- <head>
68
- <meta charset="utf-8">
69
- <title>Tilemap Scene</title>
70
- <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
71
- <script src="https://unpkg.com/aframe-extras@6.1.1/dist/aframe-extras.loaders.min.js"></script>
72
- </head>
73
- <body>
74
- <a-scene>
75
- <a-assets>
 
 
76
  {assets_html}
77
- </a-assets>
78
-
79
- <!-- Lighting -->
80
- <a-entity light="type: ambient; color: #BBB"></a-entity>
81
- <a-entity
82
- light="type: directional; color: #FFF; intensity: 0.6"
83
- position="1 1 0">
84
- </a-entity>
85
- <a-entity
86
- light="type: point; intensity: 0.6"
87
- position="0 5 0">
88
- </a-entity>
89
-
90
- <!-- Camera -->
91
- <a-entity
92
- camera
93
- look-controls
94
- position="0 {grid_size} {grid_size}">
95
- </a-entity>
96
-
97
- <!-- Container for tiles & models -->
98
- <a-entity id="tilemap"></a-entity>
99
- </a-scene>
100
-
101
- <script>
102
  document.addEventListener('DOMContentLoaded', function() {{
103
- var scene = document.querySelector('a-scene');
104
- var tilemap = document.querySelector('#tilemap');
105
- var textures = [{texture_list}];
106
- var models = [{model_js_array}];
107
  var grid = {grid_size};
108
 
109
  for (var i = 0; i < grid; i++) {{
@@ -116,18 +150,20 @@ def main():
116
  tile.setAttribute('width', 1);
117
  tile.setAttribute('height', 0.1);
118
  tile.setAttribute('depth', 1);
119
- var tex = textures[Math.floor(Math.random() * textures.length)];
120
- tile.setAttribute('material', 'src: ' + tex + '; repeat: 1 1');
121
  tile.setAttribute('position', x + ' 0 ' + z);
122
  tilemap.appendChild(tile);
123
 
124
  // Random model
125
  var m = models[Math.floor(Math.random() * models.length)];
126
  var ent = document.createElement('a-entity');
127
- if (m.ext === '.obj') {{
128
- ent.setAttribute('obj-model', 'obj: ' + m.id);
129
- }} else {{
130
  ent.setAttribute('gltf-model', m.id);
 
 
 
 
131
  }}
132
  ent.setAttribute('scale', '0.5 0.5 0.5');
133
  ent.setAttribute('position', x + ' 0.5 ' + z);
@@ -144,9 +180,9 @@ def main():
144
  ground.setAttribute('position', '0 -0.05 0');
145
  scene.insertBefore(ground, scene.firstChild);
146
  }});
147
- </script>
148
- </body>
149
- </html>
150
  """
151
 
152
  st.components.v1.html(html, height=600, scrolling=False)
 
4
 
5
  @st.cache_data
6
  def scan_assets():
7
+ """Discover textures, bump maps, glTF models, and OBJ(+MTL) pairs."""
 
8
  files = [f for f in os.listdir() if os.path.isfile(f)]
9
+ img_exts = (".jpg", ".jpeg", ".png", ".gif")
10
+
11
+ # Textures (exclude bump/normal)
12
  textures = [
13
  f for f in files
14
  if f.lower().endswith(img_exts)
15
  and not any(tag in f.lower() for tag in ("bump", "normal"))
16
  ]
17
+
18
+ # Bump/NORMAL map (just take the first one, if any)
19
  bump_maps = [
20
  f for f in files
21
  if f.lower().endswith(img_exts)
22
  and any(tag in f.lower() for tag in ("bump", "normal"))
23
  ]
24
+
25
+ # glTF models
26
+ gltf_models = [f for f in files if f.lower().endswith((".glb", ".gltf"))]
27
+
28
+ # OBJ models + their MTL partners
29
+ obj_models = [f for f in files if f.lower().endswith(".obj")]
30
+ mtl_files = {os.path.splitext(f)[0]: f for f in files if f.lower().endswith(".mtl")}
31
+
32
+ models = []
33
+ idx = 0
34
+
35
+ # Register glTF entries
36
+ for gltf in gltf_models:
37
+ models.append({
38
+ "type": "gltf",
39
+ "asset_id": f"model{idx}",
40
+ "src": gltf
41
+ })
42
+ idx += 1
43
+
44
+ # Register OBJ entries (with optional MTL)
45
+ for obj in obj_models:
46
+ base = os.path.splitext(obj)[0]
47
+ mtl = mtl_files.get(base)
48
+ entry = {
49
+ "type": "obj",
50
+ "obj_id": f"model{idx}-obj",
51
+ "obj": obj,
52
+ "mtl_id": f"model{idx}-mtl" if mtl else None,
53
+ "mtl": mtl
54
+ }
55
+ models.append(entry)
56
+ idx += 1
57
+
58
+ return textures, bump_maps, models
59
 
60
  def main():
61
+ st.title("🔳 A-Frame Tilemap with Random 3D Models")
62
+ grid_size = st.sidebar.slider("Grid Size", 1, 20, 10)
 
63
 
64
+ textures, bump_maps, models = scan_assets()
65
+ if not textures or not models:
66
+ st.warning("⚠️ Drop at least one image (jpg/png) **and** one glb/obj model (with optional mtl) into this folder.")
67
  return
68
 
69
+ # Build <a-assets>
70
  asset_tags = []
71
  for i, tex in enumerate(textures):
72
  asset_tags.append(f'<img id="tex{i}" src="{tex}">')
73
+
74
  if bump_maps:
75
+ asset_tags.append(f'<img id="bump0" src="{bump_maps[0]}">')
76
+
77
+ for m in models:
78
+ if m["type"] == "gltf":
79
+ asset_tags.append(f'<a-asset-item id="{m["asset_id"]}" src="{m["src"]}"></a-asset-item>')
80
+ else:
81
+ asset_tags.append(f'<a-asset-item id="{m["obj_id"]}" src="{m["obj"]}"></a-asset-item>')
82
+ if m["mtl_id"]:
83
+ asset_tags.append(f'<a-asset-item id="{m["mtl_id"]}" src="{m["mtl"]}"></a-asset-item>')
84
 
85
  assets_html = "\n ".join(asset_tags)
 
 
 
 
 
86
 
87
+ # JS arrays
88
+ tex_js = ", ".join(f'"#tex{i}"' for i in range(len(textures)))
89
+ has_bump = "true" if bump_maps else "false"
90
+ models_js = []
91
+ for m in models:
92
+ if m["type"] == "gltf":
93
+ models_js.append(f'{{type:"gltf", id:"#%s"}}' % m["asset_id"])
94
+ else:
95
+ mtl_part = f', mtl:"#%s"' % m["mtl_id"] if m["mtl_id"] else ""
96
+ models_js.append(f'{{type:"obj", obj:"#%s"{mtl}}}' % (m["obj_id"], mtl=mtl_part))
97
+ models_js = ", ".join(models_js)
98
+
99
+ # Ground material
100
  if bump_maps:
101
+ ground_mat = "ground.setAttribute('material','color:#228B22; bumpMap:#bump0; bumpScale:0.2');"
 
 
 
102
  else:
103
+ ground_mat = "ground.setAttribute('material','color:#228B22');"
104
 
105
+ # Final HTML
106
  html = f"""
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head>
110
+ <meta charset="utf-8">
111
+ <title>Tilemap Scene</title>
112
+ <!-- Core A-Frame -->
113
+ <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
114
+ <!-- Loaders for OBJ & glTF -->
115
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>
116
+ </head>
117
+ <body>
118
+ <a-scene>
119
+ <a-assets>
120
  {assets_html}
121
+ </a-assets>
122
+
123
+ <!-- Lights -->
124
+ <a-entity light="type: ambient; color: #BBB"></a-entity>
125
+ <a-entity light="type: directional; color: #FFF; intensity: 0.6" position="1 1 0"></a-entity>
126
+ <a-entity light="type: point; intensity: 0.6" position="0 5 0"></a-entity>
127
+
128
+ <!-- Camera -->
129
+ <a-entity camera look-controls position="0 {grid_size} {grid_size}"></a-entity>
130
+
131
+ <!-- Container -->
132
+ <a-entity id="tilemap"></a-entity>
133
+ </a-scene>
134
+
135
+ <script>
 
 
 
 
 
 
 
 
 
 
136
  document.addEventListener('DOMContentLoaded', function() {{
137
+ var scene = document.querySelector('a-scene');
138
+ var tilemap = document.querySelector('#tilemap');
139
+ var textures = [{tex_js}];
140
+ var models = [{models_js}];
141
  var grid = {grid_size};
142
 
143
  for (var i = 0; i < grid; i++) {{
 
150
  tile.setAttribute('width', 1);
151
  tile.setAttribute('height', 0.1);
152
  tile.setAttribute('depth', 1);
153
+ var tidx = Math.floor(Math.random() * textures.length);
154
+ tile.setAttribute('material', 'src:' + textures[tidx] + '; repeat:1 1');
155
  tile.setAttribute('position', x + ' 0 ' + z);
156
  tilemap.appendChild(tile);
157
 
158
  // Random model
159
  var m = models[Math.floor(Math.random() * models.length)];
160
  var ent = document.createElement('a-entity');
161
+ if (m.type === 'gltf') {{
 
 
162
  ent.setAttribute('gltf-model', m.id);
163
+ }} else {{
164
+ var cmd = 'obj: ' + m.obj;
165
+ if (m.mtl) cmd += '; mtl: ' + m.mtl;
166
+ ent.setAttribute('obj-model', cmd);
167
  }}
168
  ent.setAttribute('scale', '0.5 0.5 0.5');
169
  ent.setAttribute('position', x + ' 0.5 ' + z);
 
180
  ground.setAttribute('position', '0 -0.05 0');
181
  scene.insertBefore(ground, scene.firstChild);
182
  }});
183
+ </script>
184
+ </body>
185
+ </html>
186
  """
187
 
188
  st.components.v1.html(html, height=600, scrolling=False)