Skip to content

Instantly share code, notes, and snippets.

@TheNextGuy32
Created October 31, 2024 16:28
Show Gist options
  • Save TheNextGuy32/8869694263ca12209f687c8ad19d087a to your computer and use it in GitHub Desktop.
Save TheNextGuy32/8869694263ca12209f687c8ad19d087a to your computer and use it in GitHub Desktop.
Can you help me write idiomatic Godot code?
extends Node3D
var base_url: String = "http://127.0.0.1:5000"
var roblox_user_id: String = "427590401"
func _ready():
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_get_owned_items_completed)
var url = base_url + "/items/moderation_status?moderationStatus=APPROVED&pageSize=16"
# http_request.request(url)
func _on_get_owned_items_completed(result, response_code, headers, body):
if result != HTTPRequest.RESULT_SUCCESS:
emit_signal("load_error", "Request failed with code: " + str(result))
return
if response_code != 200:
emit_signal("load_error", "Server returned error code: " + str(response_code))
return
var json = JSON.parse_string(body.get_string_from_utf8())
var items = json["items"] # Assuming the response has an "items" key
var num_items = items.size()
var grid_size = ceil(sqrt(num_items))
var spacing = 18
var total_width = grid_size * spacing
var total_height = grid_size * spacing
var offset_x = -total_width / 2
var offset_y = -total_height / 2
for i in range(num_items):
var row = floor(i / grid_size)
var col = i % int(grid_size)
var x_pos = col * spacing + offset_x
var y_pos = row * spacing + offset_y
var item = items[i]
var components = JSON.parse_string(item["components"])
if components.has("ImageGuid") && components.has("RenderExtrusion"):
var renderExtrusion = components["RenderExtrusion"]
create_mesh_extrusion(Vector3(x_pos, y_pos, 0), components["ImageGuid"]["Image Guid"], renderExtrusion)
func create_mesh_extrusion(pos: Vector3, guid: String, render_extrusion: Dictionary) -> MeshInstance3D:
var mesh_instance = MeshInstance3D.new()
add_child(mesh_instance)
var transform = Transform3D.IDENTITY
transform.origin = pos
mesh_instance.transform = transform
# Set up the script
var script = load("res://MeshExtrusion.gd")
mesh_instance.set_script(script)
mesh_instance.image_guid = guid
mesh_instance.render_extrusion = render_extrusion
mesh_instance._ready()
return mesh_instance
extends MeshInstance3D
signal mesh_loaded(mesh_instance)
signal load_error(error_message)
var base_url: String = "http://127.0.0.1:5000"
@export var image_guid: String = ""
@export var render_extrusion: Dictionary = {}
func _ready():
if image_guid.is_empty():
push_error("[MeshInstance3D] No image_guid provided")
return
request_mesh()
func request_mesh():
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_request_completed)
http_request.request(base_url + "/image?imageGuid=" + image_guid)
func _on_request_completed(result, response_code, headers, body):
if result != HTTPRequest.RESULT_SUCCESS:
emit_signal("load_error", "Request failed with code: " + str(result))
return
if response_code != 200:
emit_signal("load_error", "Server returned error code: " + str(response_code))
return
var json = JSON.parse_string(body.get_string_from_utf8())
var imageObject = json["image"]
var colorString = imageObject["image"]
mesh = VoxelMeshGenerator.generate_mesh(colorString, render_extrusion)
emit_signal("mesh_loaded", self)
class_name VoxelMeshGenerator
extends RefCounted
const VOXEL_SIZE = 1
static func parse_color_data(input_string: String) -> Array:
var colors = []
var color_strings = input_string.split(";")
# First convert all strings to Color objects
for color_str in color_strings:
var components = color_str.split(",")
if components.size() == 4:
var r = float(components[0])
var g = float(components[1])
var b = float(components[2])
var a = 1 - float(components[3]) # Invert alpha
colors.append(Color(r, g, b, a))
# Then convert to 2D array
var image_colors = []
var index = 0
for i in range(16):
var row = []
for j in range(16):
row.append(colors[index])
index += 1
image_colors.append(row)
return image_colors
static func generate_mesh(color_data_string: String, render_extrusion: Dictionary) -> Mesh:
# Parse size and position from render_extrusion
var size_str = render_extrusion.get("Size", "16,16,16").split(",")
var size = Vector3(float(size_str[0]), float(size_str[1]), float(size_str[2]))
size *= VOXEL_SIZE
var pos_str = render_extrusion.get("Position", "0,0,0").split(",")
var rel_pos = Vector3(float(pos_str[0]), float(pos_str[1]), float(pos_str[2]))
rel_pos *= VOXEL_SIZE
# Create material
var mat = StandardMaterial3D.new()
mat.vertex_color_use_as_albedo = true
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
var image_colors = parse_color_data(color_data_string)
var surface_tool = SurfaceTool.new()
surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
surface_tool.set_material(mat)
# Create a 3D array to easily check neighbors
var voxels = []
for y in range(16):
var plane = []
for x in range(16):
plane.append(image_colors[15-y][x])
voxels.append(plane)
# Calculate offset to center the mesh
var offset_x = 0 #-8.0 # Half of 16
var offset_y = 0 #-8.0 # Half of 16
for y in range(16):
for x in range(16):
var color = voxels[y][x]
if color.a == 0:
continue
var transform = Transform3D(Basis(), Vector3(x + offset_x, y + offset_y, 0) + rel_pos)
add_optimized_box(surface_tool, transform, Vector2(size.x/16, size.y/16), size.z, color, voxels, x, y)
surface_tool.generate_normals()
return surface_tool.commit()
static func has_neighbor(voxels: Array, x: int, y: int, dx: int, dy: int) -> bool:
var nx = x + dx
var ny = y + dy
if nx < 0 or nx >= 16 or ny < 0 or ny >= 16:
return false
return voxels[ny][nx].a > 0
static func add_optimized_box(surface_tool: SurfaceTool, transform: Transform3D, size: Vector2, depth: float, color: Color, voxels: Array, x: int, y: int):
# Scale the transform's origin by the voxel size to position voxels correctly
var scalingSize = Vector3(size.x, size.y, depth)
var scaled_transform = transform
scaled_transform.origin = transform.origin * scalingSize
var vertices = [
Vector3(-0.5, -0.5, -0.5),
Vector3( 0.5, -0.5, -0.5),
Vector3( 0.5, 0.5, -0.5),
Vector3(-0.5, 0.5, -0.5),
Vector3(-0.5, -0.5, 0.5),
Vector3( 0.5, -0.5, 0.5),
Vector3( 0.5, 0.5, 0.5),
Vector3(-0.5, 0.5, 0.5)
]
# Use scaled_transform instead of transform
for i in range(vertices.size()):
vertices[i] = scaled_transform * (vertices[i] * scalingSize)
# Only add faces if there's no neighbor in that direction
var faces = []
# Back face (facing negative Z)
faces.append([vertices[0], vertices[1], vertices[2], vertices[3]]) # Reversed winding order
# Front face (facing positive Z)
faces.append([vertices[5], vertices[4], vertices[7], vertices[6]]) # Reversed winding order
# Bottom face (facing negative Y)
if not has_neighbor(voxels, x, y, 0, -1):
faces.append([vertices[1], vertices[0], vertices[4], vertices[5]])
# Top face (facing positive Y)
if not has_neighbor(voxels, x, y, 0, 1):
faces.append([vertices[3], vertices[2], vertices[6], vertices[7]])
# Right face (facing positive X)
if not has_neighbor(voxels, x, y, 1, 0):
faces.append([vertices[2], vertices[1], vertices[5], vertices[6]])
# Left face (facing negative X)
if not has_neighbor(voxels, x, y, -1, 0):
faces.append([vertices[0], vertices[3], vertices[7], vertices[4]])
# Add only the necessary faces to the mesh
for face in faces:
surface_tool.set_color(color)
surface_tool.add_vertex(face[0])
surface_tool.add_vertex(face[1])
surface_tool.add_vertex(face[2])
surface_tool.add_vertex(face[2])
surface_tool.add_vertex(face[3])
surface_tool.add_vertex(face[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment