Skip to content

Instantly share code, notes, and snippets.

@breinbaas
Last active May 1, 2024 21:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save breinbaas/541a9fef1461c1d008f373b432b3f9d6 to your computer and use it in GitHub Desktop.
Save breinbaas/541a9fef1461c1d008f373b432b3f9d6 to your computer and use it in GitHub Desktop.

Godot - Python interaction

I need to call some specific Python code which is not easy to implement as Godot code and came up with this solution. Note that the essence of the script is that the Python code generates a dictionary with the required information and prints this as a JSON formatted string. Godot calls the script and receives the output and uses the internal JSON functionality to convert the string to a Godot JSON object. Also note that the Python script gets called from the python version that is set in the environment specific for this Python code (python-venv).

Not too difficult actually!

Python code

import sys
import json
from leveelogic.soilinvestigation.cpt import Cpt, CptConversionMethod
from leveelogic.soil.soilcollection import SoilCollection

import logging

logging.basicConfig(
    filename="read_cpts.log",
    filemode="a+",
    format="%(asctime)s %(levelname)s %(message)s",
    datefmt="%H:%M:%S",
    level=logging.INFO,
)


def read_cpts(filenames):
    result = {"cpts": [], "soils": []}

    # add soil colors
    sc = SoilCollection()
    for soil in sc.soils:
        result["soils"].append({"code": soil.code, "color": soil.color})

    # add soillayers per cpt
    for filename in filenames:
        try:
            cpt = Cpt.from_file(filename)

            sp1d = cpt.to_soilprofile1(
                minimum_layerheight=0.5,
                cptconversionmethod=CptConversionMethod.ROBERTSON,
                peat_friction_ratio=5.0,
            )
            cpt_dict = {
                "name": cpt.name,
                "x": cpt.x,
                "y": cpt.y,
                "top": cpt.top,
                "soillayers": [],
            }
            for soillayer in sp1d.soillayers:
                cpt_dict["soillayers"].append(
                    {
                        "top": soillayer.top,
                        "bottom": soillayer.bottom,
                        "code": soillayer.soilcode,
                    }
                )
            result["cpts"].append(cpt_dict)
        except Exception as e:
            logging.error(f"Got error, {e}")
            continue

    return result


if __name__ == "__main__":
    result = read_cpts(sys.argv[1:])
    print(json.dumps(result))

Godot code

Note that I have a simple 2D scene with a button and a FileDialog.

func _on_btn_add_cpts_pressed():
	$dlg_select_file.popup()

func _on_dlg_select_file_files_selected(paths):
	var output = []
	var args = ["Z:/Python/godot/read_cpts.py"]
	args.append_array(paths)
		
	OS.execute("Z:/Python/godot/.venv/Scripts/python.exe", args, output)
	var data = JSON.parse_string(output[0])
	print(data) # or do what you want with the new data object!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment