Compare commits
10 Commits
fc137e2fb2
...
1d54729ed5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d54729ed5 | ||
|
|
a58cfe74a1 | ||
|
|
a232425980 | ||
|
|
75770bb7ff | ||
|
|
4e77198656 | ||
|
|
7c24dd92b0 | ||
|
|
c3c846fb22 | ||
|
|
a1fa6e7e57 | ||
|
|
ea7ef3ace9 | ||
|
|
28e224326c |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "extensions/godot-cpp"]
|
||||||
|
path = extensions/godot-cpp
|
||||||
|
url = git@github.com:godotengine/godot-cpp.git
|
||||||
BIN
assets/base_settler.blend
Normal file
BIN
assets/base_settler.blend
Normal file
Binary file not shown.
53
assets/base_settler.blend.import
Normal file
53
assets/base_settler.blend.import
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://b6inciujfvriv"
|
||||||
|
path="res://.godot/imported/base_settler.blend-385f11519b8771f27b5c8804f07fc5a5.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/base_settler.blend"
|
||||||
|
dest_files=["res://.godot/imported/base_settler.blend-385f11519b8771f27b5c8804f07fc5a5.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type=""
|
||||||
|
nodes/root_name=""
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
nodes/import_as_skeleton_bones=false
|
||||||
|
nodes/use_node_type_suffixes=true
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
meshes/force_disable_compression=false
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
animation/import_rest_as_RESET=false
|
||||||
|
import_script/path=""
|
||||||
|
_subresources={}
|
||||||
|
blender/nodes/visible=0
|
||||||
|
blender/nodes/active_collection_only=false
|
||||||
|
blender/nodes/punctual_lights=true
|
||||||
|
blender/nodes/cameras=true
|
||||||
|
blender/nodes/custom_properties=true
|
||||||
|
blender/nodes/modifiers=1
|
||||||
|
blender/meshes/colors=false
|
||||||
|
blender/meshes/uvs=true
|
||||||
|
blender/meshes/normals=true
|
||||||
|
blender/meshes/export_geometry_nodes_instances=false
|
||||||
|
blender/meshes/tangents=true
|
||||||
|
blender/meshes/skins=2
|
||||||
|
blender/meshes/export_bones_deforming_mesh_only=false
|
||||||
|
blender/materials/unpack_enabled=true
|
||||||
|
blender/materials/export_materials=1
|
||||||
|
blender/animation/limit_playback=true
|
||||||
|
blender/animation/always_sample=true
|
||||||
|
blender/animation/group_tracks=true
|
||||||
BIN
assets/base_settler.blend1
Normal file
BIN
assets/base_settler.blend1
Normal file
Binary file not shown.
BIN
extensions/cobor_terrain_extension/.sconsign.dblite
Normal file
BIN
extensions/cobor_terrain_extension/.sconsign.dblite
Normal file
Binary file not shown.
15
extensions/cobor_terrain_extension/.vscode/c_cpp_properties.json
vendored
Normal file
15
extensions/cobor_terrain_extension/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${workspaceFolder}/../godot-cpp/**"
|
||||||
|
],
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
61
extensions/cobor_terrain_extension/.vscode/settings.json
vendored
Normal file
61
extensions/cobor_terrain_extension/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.inc": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"cerrno": "cpp",
|
||||||
|
"climits": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
65
extensions/cobor_terrain_extension/SConstruct
Normal file
65
extensions/cobor_terrain_extension/SConstruct
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from methods import print_error
|
||||||
|
|
||||||
|
|
||||||
|
libname = "cobor_terrain_extension"
|
||||||
|
projectdir = "."
|
||||||
|
|
||||||
|
localEnv = Environment(tools=["default"], PLATFORM="")
|
||||||
|
|
||||||
|
# Build profiles can be used to decrease compile times.
|
||||||
|
# You can either specify "disabled_classes", OR
|
||||||
|
# explicitly specify "enabled_classes" which disables all other classes.
|
||||||
|
# Modify the example file as needed and uncomment the line below or
|
||||||
|
# manually specify the build_profile parameter when running SCons.
|
||||||
|
|
||||||
|
# localEnv["build_profile"] = "build_profile.json"
|
||||||
|
|
||||||
|
customs = ["custom.py"]
|
||||||
|
customs = [os.path.abspath(path) for path in customs]
|
||||||
|
|
||||||
|
opts = Variables(customs, ARGUMENTS)
|
||||||
|
opts.Update(localEnv)
|
||||||
|
|
||||||
|
Help(opts.GenerateHelpText(localEnv))
|
||||||
|
|
||||||
|
env = localEnv.Clone()
|
||||||
|
|
||||||
|
if not (os.path.isdir("../godot-cpp") and os.listdir("../godot-cpp")):
|
||||||
|
print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized.
|
||||||
|
Run the following command to download godot-cpp:
|
||||||
|
|
||||||
|
git submodule update --init --recursive""")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
env = SConscript("../godot-cpp/SConstruct", {"env": env, "customs": customs})
|
||||||
|
|
||||||
|
env.Append(CPPPATH=["cobor_terrain/include/"])
|
||||||
|
env.Append(CPPPATH=["cobor_terrain/src/"])
|
||||||
|
sources = Glob("cobor_terrain/src/*.cpp")
|
||||||
|
|
||||||
|
if env["target"] in ["editor", "template_debug"]:
|
||||||
|
try:
|
||||||
|
doc_data = env.GodotCPPDocData("cobor_terrain/src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
|
||||||
|
sources.append(doc_data)
|
||||||
|
except AttributeError:
|
||||||
|
print("Not including class reference as we're targeting a pre-4.3 baseline.")
|
||||||
|
|
||||||
|
# .dev doesn't inhibit compatibility, so we don't need to key it.
|
||||||
|
# .universal just means "compatible with all relevant arches" so we don't need to key it.
|
||||||
|
suffix = env['suffix'].replace(".dev", "").replace(".universal", "")
|
||||||
|
|
||||||
|
lib_filename = "{}{}{}{}".format(env.subst('$SHLIBPREFIX'), libname, suffix, env.subst('$SHLIBSUFFIX'))
|
||||||
|
|
||||||
|
library = env.SharedLibrary(
|
||||||
|
"bin/{}/{}".format(env['platform'], lib_filename),
|
||||||
|
source=sources,
|
||||||
|
)
|
||||||
|
|
||||||
|
# copy = env.Install("{}/bin/{}/".format(projectdir, env["platform"]), library)
|
||||||
|
|
||||||
|
default_args = [library]
|
||||||
|
Default(*default_args)
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
extensions/cobor_terrain_extension/cobor_terrain.gdextension
Normal file
10
extensions/cobor_terrain_extension/cobor_terrain.gdextension
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[configuration]
|
||||||
|
|
||||||
|
entry_symbol = "cobor_terrain_library_init"
|
||||||
|
compatibility_minimum = "4.1"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
; Relative paths ensure that our GDExtension can be placed anywhere in the project directory.
|
||||||
|
|
||||||
|
linux.x86_64.debug = "./bin/linux/libcobor_terrain_extension.linux.template_debug.x86_64.so"
|
||||||
|
linux.x86_64.release = "./bin/linux/libcobor_terrain_extension.linux.template_release.x86_64.so"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dskh86iu7g6lk
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "godot_cpp/classes/ref_counted.hpp"
|
||||||
|
|
||||||
|
namespace CoborTerrain
|
||||||
|
{
|
||||||
|
class CoborTerrainEngine : public godot::RefCounted
|
||||||
|
{
|
||||||
|
GDCLASS(CoborTerrainEngine, godot::RefCounted)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CoborTerrainEngine() = default;
|
||||||
|
~CoborTerrainEngine() override = default;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef COBOR_TERRAIN_REGISTER_TYPES_H
|
||||||
|
#define COBOR_TERRAIN_REGISTER_TYPES_H
|
||||||
|
|
||||||
|
void initialize_gdextension_types();
|
||||||
|
void uninitialize_gdextension_types();
|
||||||
|
|
||||||
|
#endif // COBOR_TERRAIN_REGISTER_TYPES_H
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "cobor_terrain_engine.hpp"
|
||||||
|
|
||||||
|
using namespace CoborTerrain;
|
||||||
|
|
||||||
|
void CoborTerrain::CoborTerrainEngine::_bind_methods()
|
||||||
|
{
|
||||||
|
// godot::ClassDB::bind_method(godot::D_METHOD("parse_source_code", "source_code"), &CoborVirtualMachine::parse_source_code);
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
|||||||
|
/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||||
|
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
|
static const char *_doc_data_hash = "5784511259768951161";
|
||||||
|
static const int _doc_data_uncompressed_size = 0;
|
||||||
|
static const int _doc_data_compressed_size = 8;
|
||||||
|
static const unsigned char _doc_data_compressed[] = {
|
||||||
|
120,
|
||||||
|
218,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);
|
||||||
|
|
||||||
Binary file not shown.
@@ -0,0 +1,38 @@
|
|||||||
|
#include "register_types.h"
|
||||||
|
|
||||||
|
#include <gdextension_interface.h>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
|
#include "cobor_terrain_engine.hpp"
|
||||||
|
|
||||||
|
using namespace godot;
|
||||||
|
|
||||||
|
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
||||||
|
{
|
||||||
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GDREGISTER_CLASS(CoborTerrain::CoborTerrainEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||||
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
GDExtensionBool GDE_EXPORT cobor_terrain_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||||
|
{
|
||||||
|
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||||
|
init_obj.register_initializer(initialize_gdextension_types);
|
||||||
|
init_obj.register_terminator(uninitialize_gdextension_types);
|
||||||
|
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||||
|
|
||||||
|
return init_obj.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
52
extensions/cobor_terrain_extension/methods.py
Normal file
52
extensions/cobor_terrain_extension/methods.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
# Colors are disabled in non-TTY environments such as pipes. This means
|
||||||
|
# that if output is redirected to a file, it won't contain color codes.
|
||||||
|
# Colors are always enabled on continuous integration.
|
||||||
|
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
|
||||||
|
|
||||||
|
|
||||||
|
class ANSI(Enum):
|
||||||
|
"""
|
||||||
|
Enum class for adding ansi colorcodes directly into strings.
|
||||||
|
Automatically converts values to strings representing their
|
||||||
|
internal value, or an empty string in a non-colorized scope.
|
||||||
|
"""
|
||||||
|
|
||||||
|
RESET = "\x1b[0m"
|
||||||
|
|
||||||
|
BOLD = "\x1b[1m"
|
||||||
|
ITALIC = "\x1b[3m"
|
||||||
|
UNDERLINE = "\x1b[4m"
|
||||||
|
STRIKETHROUGH = "\x1b[9m"
|
||||||
|
REGULAR = "\x1b[22;23;24;29m"
|
||||||
|
|
||||||
|
BLACK = "\x1b[30m"
|
||||||
|
RED = "\x1b[31m"
|
||||||
|
GREEN = "\x1b[32m"
|
||||||
|
YELLOW = "\x1b[33m"
|
||||||
|
BLUE = "\x1b[34m"
|
||||||
|
MAGENTA = "\x1b[35m"
|
||||||
|
CYAN = "\x1b[36m"
|
||||||
|
WHITE = "\x1b[37m"
|
||||||
|
|
||||||
|
PURPLE = "\x1b[38;5;93m"
|
||||||
|
PINK = "\x1b[38;5;206m"
|
||||||
|
ORANGE = "\x1b[38;5;214m"
|
||||||
|
GRAY = "\x1b[38;5;244m"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
global _colorize
|
||||||
|
return str(self.value) if _colorize else ""
|
||||||
|
|
||||||
|
|
||||||
|
def print_warning(*values: object) -> None:
|
||||||
|
"""Prints a warning message with formatting."""
|
||||||
|
print(f"{ANSI.YELLOW}{ANSI.BOLD}WARNING:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def print_error(*values: object) -> None:
|
||||||
|
"""Prints an error message with formatting."""
|
||||||
|
print(f"{ANSI.RED}{ANSI.BOLD}ERROR:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||||
BIN
extensions/cobor_vm_extension/.sconsign.dblite
Normal file
BIN
extensions/cobor_vm_extension/.sconsign.dblite
Normal file
Binary file not shown.
15
extensions/cobor_vm_extension/.vscode/c_cpp_properties.json
vendored
Normal file
15
extensions/cobor_vm_extension/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${workspaceFolder}/../godot-cpp/**"
|
||||||
|
],
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
61
extensions/cobor_vm_extension/.vscode/settings.json
vendored
Normal file
61
extensions/cobor_vm_extension/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.inc": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"cerrno": "cpp",
|
||||||
|
"climits": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
65
extensions/cobor_vm_extension/SConstruct
Normal file
65
extensions/cobor_vm_extension/SConstruct
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from methods import print_error
|
||||||
|
|
||||||
|
|
||||||
|
libname = "cobor_vm_extension"
|
||||||
|
projectdir = "."
|
||||||
|
|
||||||
|
localEnv = Environment(tools=["default"], PLATFORM="")
|
||||||
|
|
||||||
|
# Build profiles can be used to decrease compile times.
|
||||||
|
# You can either specify "disabled_classes", OR
|
||||||
|
# explicitly specify "enabled_classes" which disables all other classes.
|
||||||
|
# Modify the example file as needed and uncomment the line below or
|
||||||
|
# manually specify the build_profile parameter when running SCons.
|
||||||
|
|
||||||
|
# localEnv["build_profile"] = "build_profile.json"
|
||||||
|
|
||||||
|
customs = ["custom.py"]
|
||||||
|
customs = [os.path.abspath(path) for path in customs]
|
||||||
|
|
||||||
|
opts = Variables(customs, ARGUMENTS)
|
||||||
|
opts.Update(localEnv)
|
||||||
|
|
||||||
|
Help(opts.GenerateHelpText(localEnv))
|
||||||
|
|
||||||
|
env = localEnv.Clone()
|
||||||
|
|
||||||
|
if not (os.path.isdir("../godot-cpp") and os.listdir("../godot-cpp")):
|
||||||
|
print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized.
|
||||||
|
Run the following command to download godot-cpp:
|
||||||
|
|
||||||
|
git submodule update --init --recursive""")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
env = SConscript("../godot-cpp/SConstruct", {"env": env, "customs": customs})
|
||||||
|
|
||||||
|
env.Append(CPPPATH=["cobor_vm/include/"])
|
||||||
|
env.Append(CPPPATH=["cobor_vm/src/"])
|
||||||
|
sources = Glob("cobor_vm/src/*.cpp")
|
||||||
|
|
||||||
|
if env["target"] in ["editor", "template_debug"]:
|
||||||
|
try:
|
||||||
|
doc_data = env.GodotCPPDocData("cobor_vm/src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
|
||||||
|
sources.append(doc_data)
|
||||||
|
except AttributeError:
|
||||||
|
print("Not including class reference as we're targeting a pre-4.3 baseline.")
|
||||||
|
|
||||||
|
# .dev doesn't inhibit compatibility, so we don't need to key it.
|
||||||
|
# .universal just means "compatible with all relevant arches" so we don't need to key it.
|
||||||
|
suffix = env['suffix'].replace(".dev", "").replace(".universal", "")
|
||||||
|
|
||||||
|
lib_filename = "{}{}{}{}".format(env.subst('$SHLIBPREFIX'), libname, suffix, env.subst('$SHLIBSUFFIX'))
|
||||||
|
|
||||||
|
library = env.SharedLibrary(
|
||||||
|
"bin/{}/{}".format(env['platform'], lib_filename),
|
||||||
|
source=sources,
|
||||||
|
)
|
||||||
|
|
||||||
|
# copy = env.Install("{}/bin/{}/".format(projectdir, env["platform"]), library)
|
||||||
|
|
||||||
|
default_args = [library]
|
||||||
|
Default(*default_args)
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
extensions/cobor_vm_extension/cobor_vm.gdextension
Normal file
10
extensions/cobor_vm_extension/cobor_vm.gdextension
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[configuration]
|
||||||
|
|
||||||
|
entry_symbol = "cobor_vm_library_init"
|
||||||
|
compatibility_minimum = "4.1"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
; Relative paths ensure that our GDExtension can be placed anywhere in the project directory.
|
||||||
|
|
||||||
|
linux.x86_64.debug = "./bin/linux/libcobor_vm_extension.linux.template_debug.x86_64.so"
|
||||||
|
linux.x86_64.release = "./bin/linux/libcobor_vm_extension.linux.template_release.x86_64.so"
|
||||||
1
extensions/cobor_vm_extension/cobor_vm.gdextension.uid
Normal file
1
extensions/cobor_vm_extension/cobor_vm.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ckjbrjvokj8nh
|
||||||
0
extensions/cobor_vm_extension/cobor_vm/.gdignore
Normal file
0
extensions/cobor_vm_extension/cobor_vm/.gdignore
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <godot_cpp/classes/ref_counted.hpp>
|
||||||
|
#include "constants.hpp"
|
||||||
|
|
||||||
|
namespace CoborVM
|
||||||
|
{
|
||||||
|
class CoborVirtualMachine : public godot::RefCounted
|
||||||
|
{
|
||||||
|
GDCLASS(CoborVirtualMachine, godot::RefCounted)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ExecutableStep> program;
|
||||||
|
std::vector<int32_t> register_memory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CoborVirtualMachine() = default;
|
||||||
|
~CoborVirtualMachine() override = default;
|
||||||
|
|
||||||
|
godot::PackedStringArray parse_source_code(godot::String source_code);
|
||||||
|
godot::String set_registers(int size, godot::PackedInt32Array preloaded_values);
|
||||||
|
godot::PackedInt32Array get_registers();
|
||||||
|
int get_program_counter();
|
||||||
|
int get_program_size();
|
||||||
|
godot::String run_step();
|
||||||
|
godot::String run_all();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Execution
|
||||||
|
godot::String run_executable_step(ExecutableStep step);
|
||||||
|
// Parsing
|
||||||
|
bool string_to_instruction(godot::String command_string, Instruction &outInstruction);
|
||||||
|
bool instruction_to_executable_step(Instruction instruction, godot::PackedStringArray line, ExecutableStep &outExecutableStep);
|
||||||
|
bool validate_and_parse_pointer(const godot::String &arg, int &outValue);
|
||||||
|
bool validate_and_parse_literal(const godot::String &arg, int &outValue);
|
||||||
|
};
|
||||||
|
}
|
||||||
96
extensions/cobor_vm_extension/cobor_vm/include/constants.hpp
Normal file
96
extensions/cobor_vm_extension/cobor_vm/include/constants.hpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace CoborVM
|
||||||
|
{
|
||||||
|
enum Instruction
|
||||||
|
{
|
||||||
|
EMPTY,
|
||||||
|
|
||||||
|
SET,
|
||||||
|
CLR,
|
||||||
|
MOV,
|
||||||
|
SWP,
|
||||||
|
|
||||||
|
ADD,
|
||||||
|
SUB,
|
||||||
|
MUL,
|
||||||
|
DIV,
|
||||||
|
|
||||||
|
SKIP,
|
||||||
|
JMP,
|
||||||
|
JMPTO,
|
||||||
|
|
||||||
|
EQL,
|
||||||
|
BIGR,
|
||||||
|
SMLR,
|
||||||
|
ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExecutableStep
|
||||||
|
{
|
||||||
|
Instruction instruction = Instruction::EMPTY;
|
||||||
|
int arg1;
|
||||||
|
int arg2;
|
||||||
|
int arg3;
|
||||||
|
|
||||||
|
int lineNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map from string to instruction
|
||||||
|
const std::unordered_map<std::string, Instruction> stringToInstructionMap = {
|
||||||
|
{"SET", SET},
|
||||||
|
{"CLR", CLR},
|
||||||
|
{"MOV", MOV},
|
||||||
|
{"SWP", SWP},
|
||||||
|
{"ADD", ADD},
|
||||||
|
{"SUB", SUB},
|
||||||
|
{"MUL", MUL},
|
||||||
|
{"DIV", DIV},
|
||||||
|
{"SKIP", SKIP},
|
||||||
|
{"JMP", JMP},
|
||||||
|
{"JMPTO", JMPTO},
|
||||||
|
{"EQL", EQL},
|
||||||
|
{"BIGR", BIGR},
|
||||||
|
{"SMLR", SMLR},
|
||||||
|
{"ZERO", ZERO}};
|
||||||
|
|
||||||
|
// Map from instruction to string
|
||||||
|
const std::unordered_map<Instruction, std::string> InstructionToStringMap = {
|
||||||
|
{SET, "SET"},
|
||||||
|
{CLR, "CLR"},
|
||||||
|
{MOV, "MOV"},
|
||||||
|
{SWP, "SWP"},
|
||||||
|
{ADD, "ADD"},
|
||||||
|
{SUB, "SUB"},
|
||||||
|
{MUL, "MUL"},
|
||||||
|
{DIV, "DIV"},
|
||||||
|
{SKIP, "SKIP"},
|
||||||
|
{JMP, "JMP"},
|
||||||
|
{JMPTO, "JMPTO"},
|
||||||
|
{EQL, "EQL"},
|
||||||
|
{BIGR, "BIGR"},
|
||||||
|
{SMLR, "SMLR"},
|
||||||
|
{ZERO, "ZERO"}};
|
||||||
|
|
||||||
|
// Define the expected argument types for each instruction (true = pointer, false = literal)
|
||||||
|
const std::unordered_map<Instruction, std::vector<bool>> instructionPatterns = {
|
||||||
|
{Instruction::SKIP, {}}, // No arguments
|
||||||
|
{Instruction::EMPTY, {}},
|
||||||
|
{Instruction::JMP, {false}}, // One literal argument
|
||||||
|
{Instruction::JMPTO, {false}},
|
||||||
|
{Instruction::CLR, {true}}, // One pointer argument
|
||||||
|
{Instruction::ZERO, {true}},
|
||||||
|
{Instruction::SET, {false, true}}, // One literal and one pointer argument
|
||||||
|
{Instruction::MOV, {true, true}}, // Two pointer arguments
|
||||||
|
{Instruction::SWP, {true, true}},
|
||||||
|
{Instruction::EQL, {true, true}},
|
||||||
|
{Instruction::BIGR, {true, true}},
|
||||||
|
{Instruction::SMLR, {true, true}},
|
||||||
|
{Instruction::ADD, {true, true, true}}, // Three pointer arguments
|
||||||
|
{Instruction::SUB, {true, true, true}},
|
||||||
|
{Instruction::MUL, {true, true, true}},
|
||||||
|
{Instruction::DIV, {true, true, true}},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef COBOR_VM_REGISTER_TYPES_H
|
||||||
|
#define COBOR_VM_REGISTER_TYPES_H
|
||||||
|
|
||||||
|
void initialize_gdextension_types();
|
||||||
|
void uninitialize_gdextension_types();
|
||||||
|
|
||||||
|
#endif // COBOR_VM_REGISTER_TYPES_H
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
// #include <godot_cpp/variant/utility_functions.hpp>
|
||||||
|
|
||||||
|
#include "cobor_virtual_machine.hpp"
|
||||||
|
|
||||||
|
using namespace CoborVM;
|
||||||
|
|
||||||
|
void CoborVM::CoborVirtualMachine::_bind_methods()
|
||||||
|
{
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("parse_source_code", "source_code"), &CoborVirtualMachine::parse_source_code);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("set_registers", "size", "preloaded_values"), &CoborVirtualMachine::set_registers);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("get_registers"), &CoborVirtualMachine::get_registers);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("get_program_counter"), &CoborVirtualMachine::get_program_counter);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("get_program_size"), &CoborVirtualMachine::get_program_size);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("run_step"), &CoborVirtualMachine::run_step);
|
||||||
|
godot::ClassDB::bind_method(godot::D_METHOD("run_all"), &CoborVirtualMachine::run_all);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::PackedStringArray CoborVM::CoborVirtualMachine::parse_source_code(godot::String source_code)
|
||||||
|
{
|
||||||
|
godot::PackedStringArray parseFaults;
|
||||||
|
program.clear();
|
||||||
|
|
||||||
|
source_code = source_code.to_upper();
|
||||||
|
auto lines = source_code.split("\n");
|
||||||
|
int lineNumber = 0;
|
||||||
|
for (auto &line : lines)
|
||||||
|
{
|
||||||
|
lineNumber++;
|
||||||
|
ExecutableStep step;
|
||||||
|
step.instruction = EMPTY;
|
||||||
|
step.lineNumber = lineNumber;
|
||||||
|
|
||||||
|
line = line.strip_edges();
|
||||||
|
if (!line.is_empty())
|
||||||
|
{
|
||||||
|
auto words = line.split(" ", false);
|
||||||
|
Instruction instruction;
|
||||||
|
if (!string_to_instruction(words[0], instruction))
|
||||||
|
{
|
||||||
|
parseFaults.append(godot::String("Error: Invalid instruction at line ") +
|
||||||
|
godot::String::num_int64(lineNumber) +
|
||||||
|
godot::String(": {") + line + godot::String("}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!instruction_to_executable_step(instruction, words, step))
|
||||||
|
{
|
||||||
|
parseFaults.append(godot::String("Error: Invalid arguments at line ") +
|
||||||
|
godot::String::num_int64(lineNumber) +
|
||||||
|
godot::String(": {") + line + godot::String("}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
program.emplace_back(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseFaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::String CoborVM::CoborVirtualMachine::set_registers(int size, godot::PackedInt32Array preloaded_values)
|
||||||
|
{
|
||||||
|
if (size <= 0)
|
||||||
|
return godot::String("Size must be one or higher");
|
||||||
|
register_memory = std::vector<int32_t>(size);
|
||||||
|
preloaded_values.resize(size);
|
||||||
|
int i = 0;
|
||||||
|
for (int value : preloaded_values)
|
||||||
|
{
|
||||||
|
register_memory[i] = value;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return godot::String();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::PackedInt32Array CoborVM::CoborVirtualMachine::get_registers()
|
||||||
|
{
|
||||||
|
godot::PackedInt32Array ret;
|
||||||
|
for (int32_t value : register_memory)
|
||||||
|
{
|
||||||
|
ret.append(value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CoborVM::CoborVirtualMachine::get_program_counter()
|
||||||
|
{
|
||||||
|
return register_memory[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int CoborVM::CoborVirtualMachine::get_program_size()
|
||||||
|
{
|
||||||
|
return program.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::String CoborVM::CoborVirtualMachine::run_step()
|
||||||
|
{
|
||||||
|
if (program.empty())
|
||||||
|
return godot::String("No program is compiled to run.");
|
||||||
|
if (register_memory.empty())
|
||||||
|
return godot::String("Registers are not set.");
|
||||||
|
|
||||||
|
int program_counter = register_memory[0];
|
||||||
|
if (program_counter < 0 || program_counter >= program.size())
|
||||||
|
return godot::String("Program counter pointing outside program scope: ") +
|
||||||
|
godot::String::num_int64(program_counter);
|
||||||
|
|
||||||
|
ExecutableStep step = program[program_counter];
|
||||||
|
auto err = run_executable_step(step);
|
||||||
|
if (!err.is_empty())
|
||||||
|
{
|
||||||
|
return godot::String("Execution failed at line: ") +
|
||||||
|
godot::String::num_int64(step.lineNumber) +
|
||||||
|
godot::String(" with error: ") +
|
||||||
|
err;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_memory[0]++;
|
||||||
|
return godot::String();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::String CoborVM::CoborVirtualMachine::run_all()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int program_counter = register_memory[0];
|
||||||
|
if (program.size() <= program_counter)
|
||||||
|
break;
|
||||||
|
auto result = run_step();
|
||||||
|
if (!result.is_empty())
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return godot::String();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot::String CoborVM::CoborVirtualMachine::run_executable_step(ExecutableStep step)
|
||||||
|
{
|
||||||
|
godot::String error_message;
|
||||||
|
|
||||||
|
auto check_register = [this, &error_message](int64_t reg) -> bool
|
||||||
|
{
|
||||||
|
if (reg >= register_memory.size())
|
||||||
|
{
|
||||||
|
error_message = godot::String("Pointing outside register memory at /") + godot::String::num_int64(reg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (step.instruction)
|
||||||
|
{
|
||||||
|
case EMPTY:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SET:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg2] = step.arg1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CLR:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MOV:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg2] = register_memory[step.arg1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SWP:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
std::swap(register_memory[step.arg1], register_memory[step.arg2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADD:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg3] = register_memory[step.arg1] + register_memory[step.arg2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SUB:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg3] = register_memory[step.arg1] - register_memory[step.arg2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MUL:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||||
|
return error_message;
|
||||||
|
register_memory[step.arg3] = register_memory[step.arg1] * register_memory[step.arg2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DIV:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||||
|
return error_message;
|
||||||
|
if (register_memory[step.arg2] == 0)
|
||||||
|
{
|
||||||
|
return godot::String("Dividing by zero! Check register: ") + godot::String::num_int64(step.arg2);
|
||||||
|
}
|
||||||
|
register_memory[step.arg3] = register_memory[step.arg1] / register_memory[step.arg2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SKIP:
|
||||||
|
{
|
||||||
|
register_memory[0]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JMP:
|
||||||
|
{
|
||||||
|
register_memory[0] += step.arg1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JMPTO:
|
||||||
|
{
|
||||||
|
register_memory[0] = step.arg1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EQL:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
if (register_memory[step.arg1] == register_memory[step.arg2])
|
||||||
|
register_memory[0]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BIGR:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
if (register_memory[step.arg1] < register_memory[step.arg2])
|
||||||
|
register_memory[0]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SMLR:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||||
|
return error_message;
|
||||||
|
if (register_memory[step.arg1] > register_memory[step.arg2])
|
||||||
|
register_memory[0]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ZERO:
|
||||||
|
{
|
||||||
|
if (!check_register(step.arg1))
|
||||||
|
return error_message;
|
||||||
|
if (register_memory[step.arg1] == 0)
|
||||||
|
register_memory[0]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return godot::String("Unknown instruction! This is not on you.");
|
||||||
|
}
|
||||||
|
return godot::String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoborVM::CoborVirtualMachine::string_to_instruction(godot::String command_string, Instruction &outInstruction)
|
||||||
|
{
|
||||||
|
std::string cmd = command_string.utf8().get_data();
|
||||||
|
|
||||||
|
auto it = stringToInstructionMap.find(cmd);
|
||||||
|
if (it != stringToInstructionMap.end())
|
||||||
|
{
|
||||||
|
outInstruction = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoborVM::CoborVirtualMachine::instruction_to_executable_step(Instruction instruction, godot::PackedStringArray line, ExecutableStep &outExecutableStep)
|
||||||
|
{
|
||||||
|
outExecutableStep.instruction = instruction;
|
||||||
|
|
||||||
|
auto it = instructionPatterns.find(instruction);
|
||||||
|
if (it == instructionPatterns.end())
|
||||||
|
{
|
||||||
|
return false; // Unknown instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<bool> &pattern = it->second;
|
||||||
|
if (line.size() != pattern.size() + 1)
|
||||||
|
{ // +1 for the instruction itself
|
||||||
|
return false; // Incorrect number of arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg1 = 0, arg2 = 0, arg3 = 0;
|
||||||
|
for (size_t i = 0; i < pattern.size(); ++i)
|
||||||
|
{
|
||||||
|
bool isPointer = pattern[i];
|
||||||
|
godot::String arg = line[i + 1]; // +1 to skip the instruction
|
||||||
|
|
||||||
|
if (isPointer)
|
||||||
|
{
|
||||||
|
if (!validate_and_parse_pointer(arg, (i == 0) ? arg1 : (i == 1) ? arg2
|
||||||
|
: arg3))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!validate_and_parse_literal(arg, (i == 0) ? arg1 : (i == 1) ? arg2
|
||||||
|
: arg3))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outExecutableStep.arg1 = arg1;
|
||||||
|
outExecutableStep.arg2 = arg2;
|
||||||
|
outExecutableStep.arg3 = arg3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoborVM::CoborVirtualMachine::validate_and_parse_pointer(const godot::String &arg, int &outValue)
|
||||||
|
{
|
||||||
|
if (!arg.begins_with("/"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
godot::String trimmedArg = arg.trim_prefix("/");
|
||||||
|
if (!trimmedArg.is_valid_int())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outValue = trimmedArg.to_int();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoborVM::CoborVirtualMachine::validate_and_parse_literal(const godot::String &arg, int &outValue)
|
||||||
|
{
|
||||||
|
if (!arg.is_valid_int())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outValue = arg.to_int();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Binary file not shown.
BIN
extensions/cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
Binary file not shown.
@@ -0,0 +1,20 @@
|
|||||||
|
/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||||
|
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
|
static const char *_doc_data_hash = "-3606861580427548082";
|
||||||
|
static const int _doc_data_uncompressed_size = 0;
|
||||||
|
static const int _doc_data_compressed_size = 8;
|
||||||
|
static const unsigned char _doc_data_compressed[] = {
|
||||||
|
120,
|
||||||
|
218,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);
|
||||||
|
|
||||||
BIN
extensions/cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
Binary file not shown.
@@ -0,0 +1,38 @@
|
|||||||
|
#include "register_types.h"
|
||||||
|
|
||||||
|
#include <gdextension_interface.h>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
|
#include "cobor_virtual_machine.hpp"
|
||||||
|
|
||||||
|
using namespace godot;
|
||||||
|
|
||||||
|
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
||||||
|
{
|
||||||
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GDREGISTER_CLASS(CoborVM::CoborVirtualMachine);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||||
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
GDExtensionBool GDE_EXPORT cobor_vm_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||||
|
{
|
||||||
|
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||||
|
init_obj.register_initializer(initialize_gdextension_types);
|
||||||
|
init_obj.register_terminator(uninitialize_gdextension_types);
|
||||||
|
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||||
|
|
||||||
|
return init_obj.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
extensions/cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
Binary file not shown.
1
extensions/cobor_vm_extension/example.gdextension.uid
Normal file
1
extensions/cobor_vm_extension/example.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dku1li0a05p5h
|
||||||
52
extensions/cobor_vm_extension/methods.py
Normal file
52
extensions/cobor_vm_extension/methods.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
# Colors are disabled in non-TTY environments such as pipes. This means
|
||||||
|
# that if output is redirected to a file, it won't contain color codes.
|
||||||
|
# Colors are always enabled on continuous integration.
|
||||||
|
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
|
||||||
|
|
||||||
|
|
||||||
|
class ANSI(Enum):
|
||||||
|
"""
|
||||||
|
Enum class for adding ansi colorcodes directly into strings.
|
||||||
|
Automatically converts values to strings representing their
|
||||||
|
internal value, or an empty string in a non-colorized scope.
|
||||||
|
"""
|
||||||
|
|
||||||
|
RESET = "\x1b[0m"
|
||||||
|
|
||||||
|
BOLD = "\x1b[1m"
|
||||||
|
ITALIC = "\x1b[3m"
|
||||||
|
UNDERLINE = "\x1b[4m"
|
||||||
|
STRIKETHROUGH = "\x1b[9m"
|
||||||
|
REGULAR = "\x1b[22;23;24;29m"
|
||||||
|
|
||||||
|
BLACK = "\x1b[30m"
|
||||||
|
RED = "\x1b[31m"
|
||||||
|
GREEN = "\x1b[32m"
|
||||||
|
YELLOW = "\x1b[33m"
|
||||||
|
BLUE = "\x1b[34m"
|
||||||
|
MAGENTA = "\x1b[35m"
|
||||||
|
CYAN = "\x1b[36m"
|
||||||
|
WHITE = "\x1b[37m"
|
||||||
|
|
||||||
|
PURPLE = "\x1b[38;5;93m"
|
||||||
|
PINK = "\x1b[38;5;206m"
|
||||||
|
ORANGE = "\x1b[38;5;214m"
|
||||||
|
GRAY = "\x1b[38;5;244m"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
global _colorize
|
||||||
|
return str(self.value) if _colorize else ""
|
||||||
|
|
||||||
|
|
||||||
|
def print_warning(*values: object) -> None:
|
||||||
|
"""Prints a warning message with formatting."""
|
||||||
|
print(f"{ANSI.YELLOW}{ANSI.BOLD}WARNING:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def print_error(*values: object) -> None:
|
||||||
|
"""Prints an error message with formatting."""
|
||||||
|
print(f"{ANSI.RED}{ANSI.BOLD}ERROR:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||||
1
extensions/godot-cpp
Submodule
1
extensions/godot-cpp
Submodule
Submodule extensions/godot-cpp added at d502d8e8aa
70
nodes/camera/controllable_camera.gd
Normal file
70
nodes/camera/controllable_camera.gd
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
extends Camera3D
|
||||||
|
|
||||||
|
@export var base_move_speed := 5.0
|
||||||
|
@export var min_move_speed := 1.0
|
||||||
|
@export var max_move_speed := 20.0
|
||||||
|
@export var rotation_speed := 0.002
|
||||||
|
|
||||||
|
var input_delay_over := false
|
||||||
|
var current_move_speed := base_move_speed
|
||||||
|
var mouse_delta := Vector2.ZERO
|
||||||
|
var mouse_pos := Vector2.ZERO
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if Input.is_action_just_pressed("camera_control"):
|
||||||
|
mouse_pos = get_viewport().get_mouse_position()
|
||||||
|
input_delay_over = false
|
||||||
|
get_tree().create_timer(0.15).timeout.connect(
|
||||||
|
func():
|
||||||
|
if Input.is_action_pressed("camera_control"):
|
||||||
|
input_delay_over = true
|
||||||
|
)
|
||||||
|
if Input.is_action_pressed("camera_control") and input_delay_over:
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
|
handle_movement(delta)
|
||||||
|
handle_rotation()
|
||||||
|
else:
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||||
|
if Input.is_action_just_released("camera_control") and input_delay_over:
|
||||||
|
Input.warp_mouse(mouse_pos)
|
||||||
|
|
||||||
|
func _unhandled_input(event):
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
handle_scroll_wheel(event)
|
||||||
|
if event is InputEventMouseMotion:
|
||||||
|
mouse_delta = event.relative
|
||||||
|
|
||||||
|
func handle_movement(delta: float) -> void:
|
||||||
|
var input_dir = Vector3.ZERO
|
||||||
|
if Input.is_key_pressed(KEY_W):
|
||||||
|
input_dir.z -= 1
|
||||||
|
if Input.is_key_pressed(KEY_S):
|
||||||
|
input_dir.z += 1
|
||||||
|
if Input.is_key_pressed(KEY_A):
|
||||||
|
input_dir.x -= 1
|
||||||
|
if Input.is_key_pressed(KEY_D):
|
||||||
|
input_dir.x += 1
|
||||||
|
if Input.is_key_pressed(KEY_E):
|
||||||
|
input_dir.y += 1
|
||||||
|
if Input.is_key_pressed(KEY_Q):
|
||||||
|
input_dir.y -= 1
|
||||||
|
|
||||||
|
if input_dir.length() > 0:
|
||||||
|
input_dir = input_dir.normalized()
|
||||||
|
translate(input_dir * current_move_speed * delta)
|
||||||
|
|
||||||
|
func handle_rotation() -> void:
|
||||||
|
var current_rotation_x = rotation.x - mouse_delta.y * rotation_speed
|
||||||
|
current_rotation_x = clamp(current_rotation_x, -1.5, 1.5)
|
||||||
|
var current_rotation_y = rotation.y - mouse_delta.x * rotation_speed
|
||||||
|
rotation = Vector3(current_rotation_x, current_rotation_y, 0)
|
||||||
|
mouse_delta = Vector2.ZERO
|
||||||
|
|
||||||
|
func handle_scroll_wheel(event: InputEventMouseButton ) -> void:
|
||||||
|
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||||
|
adjust_move_speed(1.0)
|
||||||
|
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||||
|
adjust_move_speed(-1.0)
|
||||||
|
|
||||||
|
func adjust_move_speed(delta: float) -> void:
|
||||||
|
current_move_speed = clamp(current_move_speed + delta, min_move_speed, max_move_speed)
|
||||||
1
nodes/camera/controllable_camera.gd.uid
Normal file
1
nodes/camera/controllable_camera.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://le0spo0q018k
|
||||||
9
nodes/camera/controllable_camera.tscn
Normal file
9
nodes/camera/controllable_camera.tscn
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cy0nvmw51bwof"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://le0spo0q018k" path="res://nodes/camera/controllable_camera.gd" id="1_fgom1"]
|
||||||
|
|
||||||
|
[node name="ControllableCamera" type="Camera3D"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
|
script = ExtResource("1_fgom1")
|
||||||
|
|
||||||
|
[node name="VoxelViewer" type="VoxelViewer" parent="."]
|
||||||
3
nodes/game.tscn
Normal file
3
nodes/game.tscn
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gd_scene format=3 uid="uid://d0b7m4vykcfy2"]
|
||||||
|
|
||||||
|
[node name="Game" type="Node"]
|
||||||
49
nodes/robots/RobotScene.tscn
Normal file
49
nodes/robots/RobotScene.tscn
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
[gd_scene load_steps=12 format=3 uid="uid://b84ihb5xw37pm"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://chem70rrdwjpg" path="res://nodes/robots/robot.tscn" id="1_p4ude"]
|
||||||
|
[ext_resource type="VoxelBlockyLibrary" uid="uid://bsue4rd3wdfsl" path="res://nodes/world/BlockLibrary.tres" id="2_x03q5"]
|
||||||
|
[ext_resource type="Material" uid="uid://de6s8en5fcyyw" path="res://nodes/world/BlockMaterial.tres" id="3_k18g4"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ddyulj4dsrkms" path="res://nodes/world/terrain_editor.tscn" id="4_h5ql1"]
|
||||||
|
[ext_resource type="Script" uid="uid://cp4pflpo7neyq" path="res://nodes/world/Terrain.gd" id="4_x03q5"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cy0nvmw51bwof" path="res://nodes/camera/controllable_camera.tscn" id="5_cctyy"]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_e1sxe"]
|
||||||
|
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||||
|
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_llm6e"]
|
||||||
|
sky_material = SubResource("ProceduralSkyMaterial_e1sxe")
|
||||||
|
|
||||||
|
[sub_resource type="Environment" id="Environment_5yot8"]
|
||||||
|
background_mode = 2
|
||||||
|
sky = SubResource("Sky_llm6e")
|
||||||
|
|
||||||
|
[sub_resource type="VoxelGeneratorFlat" id="VoxelGeneratorFlat_llm6e"]
|
||||||
|
channel = 0
|
||||||
|
|
||||||
|
[sub_resource type="VoxelMesherBlocky" id="VoxelMesherBlocky_jq1ic"]
|
||||||
|
library = ExtResource("2_x03q5")
|
||||||
|
|
||||||
|
[node name="Robots" type="Node"]
|
||||||
|
|
||||||
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
|
environment = SubResource("Environment_5yot8")
|
||||||
|
|
||||||
|
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||||
|
transform = Transform3D(-0.866024, -0.433016, 0.250001, 0, 0.499998, 0.866026, -0.500003, 0.749999, -0.43301, 0, 0, 0)
|
||||||
|
shadow_enabled = true
|
||||||
|
|
||||||
|
[node name="Robot" parent="." instance=ExtResource("1_p4ude")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.5, 0.5)
|
||||||
|
|
||||||
|
[node name="VoxelTerrain" type="VoxelTerrain" parent="."]
|
||||||
|
generator = SubResource("VoxelGeneratorFlat_llm6e")
|
||||||
|
mesher = SubResource("VoxelMesherBlocky_jq1ic")
|
||||||
|
bounds = AABB(-1040, -32, -1040, 2080, 96, 2080)
|
||||||
|
material_override = ExtResource("3_k18g4")
|
||||||
|
script = ExtResource("4_x03q5")
|
||||||
|
|
||||||
|
[node name="TerrainEditor" parent="VoxelTerrain" instance=ExtResource("4_h5ql1")]
|
||||||
|
|
||||||
|
[node name="ControllableCamera" parent="." instance=ExtResource("5_cctyy")]
|
||||||
|
transform = Transform3D(0.97668, -0.143377, 0.159808, 0, 0.744336, 0.667805, -0.214699, -0.652232, 0.726979, 1.39679, 4.07542, 4.92893)
|
||||||
65
nodes/robots/coding/cpu.gd
Normal file
65
nodes/robots/coding/cpu.gd
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
class_name CPU
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
signal cpu_tick
|
||||||
|
|
||||||
|
var cobor_vm := CoborVirtualMachine.new()
|
||||||
|
var running := false
|
||||||
|
var register_size := 16
|
||||||
|
var modules : Array[Module]
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
cobor_vm.set_registers(register_size,[])
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
var register_index := 1
|
||||||
|
for child in get_children():
|
||||||
|
if child is Module:
|
||||||
|
var module := child as Module
|
||||||
|
modules.push_back(module)
|
||||||
|
module.set_reserved_registers(register_index)
|
||||||
|
register_index += module.get_register_reservation_size()
|
||||||
|
if $ProgrammingUI != null:
|
||||||
|
$ProgrammingUI.memory_setup()
|
||||||
|
|
||||||
|
func show_ui(show:bool)->void:
|
||||||
|
$ProgrammingUI.visible = show
|
||||||
|
|
||||||
|
func run_step() -> void:
|
||||||
|
if not running:
|
||||||
|
cobor_vm.set_registers(register_size,[])
|
||||||
|
running = true
|
||||||
|
_tick()
|
||||||
|
|
||||||
|
func run() -> void:
|
||||||
|
if not running:
|
||||||
|
cobor_vm.set_registers(register_size,[])
|
||||||
|
running = true
|
||||||
|
$CPUClock.start()
|
||||||
|
|
||||||
|
func _tick()->void:
|
||||||
|
for module in modules:
|
||||||
|
module.early_tick()
|
||||||
|
var err := cobor_vm.run_step()
|
||||||
|
if not err.is_empty():
|
||||||
|
print(err)
|
||||||
|
if cobor_vm.get_program_counter() >= cobor_vm.get_program_size():
|
||||||
|
stop()
|
||||||
|
for module in modules:
|
||||||
|
module.late_tick()
|
||||||
|
emit_signal("cpu_tick")
|
||||||
|
|
||||||
|
func pause()->void:
|
||||||
|
$CPUClock.stop()
|
||||||
|
|
||||||
|
func stop()->void:
|
||||||
|
running = false
|
||||||
|
$CPUClock.stop()
|
||||||
|
|
||||||
|
func compile_code(source_code: String)->void:
|
||||||
|
var errors := cobor_vm.parse_source_code(source_code)
|
||||||
|
if errors.is_empty():
|
||||||
|
print("Compiling Ok!")
|
||||||
|
else:
|
||||||
|
for error in errors:
|
||||||
|
print(error)
|
||||||
1
nodes/robots/coding/cpu.gd.uid
Normal file
1
nodes/robots/coding/cpu.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b87ksbp5mjn2a
|
||||||
13
nodes/robots/coding/cpu.tscn
Normal file
13
nodes/robots/coding/cpu.tscn
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://crtis0eyywl61"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://b87ksbp5mjn2a" path="res://nodes/robots/coding/cpu.gd" id="1_mh3k1"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c2es6v8lb8tug" path="res://nodes/robots/coding/programming_ui.tscn" id="2_pm1m8"]
|
||||||
|
|
||||||
|
[node name="CPU" type="Node"]
|
||||||
|
script = ExtResource("1_mh3k1")
|
||||||
|
|
||||||
|
[node name="CPUClock" type="Timer" parent="."]
|
||||||
|
|
||||||
|
[node name="ProgrammingUI" parent="." instance=ExtResource("2_pm1m8")]
|
||||||
|
|
||||||
|
[connection signal="timeout" from="CPUClock" to="." method="_tick"]
|
||||||
20
nodes/robots/coding/memory_entry.tscn
Normal file
20
nodes/robots/coding/memory_entry.tscn
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[gd_scene format=3 uid="uid://dqwi5rekytyds"]
|
||||||
|
|
||||||
|
[node name="memory_entry" type="HBoxContainer"]
|
||||||
|
|
||||||
|
[node name="address" type="Label" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "/0 = "
|
||||||
|
|
||||||
|
[node name="value" type="SpinBox" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
value = 4.0
|
||||||
|
rounded = true
|
||||||
|
allow_greater = true
|
||||||
|
allow_lesser = true
|
||||||
|
alignment = 1
|
||||||
|
editable = false
|
||||||
|
|
||||||
|
[node name="type" type="Label" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "[X] Click"
|
||||||
53
nodes/robots/coding/programming_ui.gd
Normal file
53
nodes/robots/coding/programming_ui.gd
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
@onready var code_editor := $%Code as CodeEdit
|
||||||
|
@onready var memory := $%Memory as VBoxContainer
|
||||||
|
@onready var memory_entry := load("uid://dqwi5rekytyds") as PackedScene
|
||||||
|
|
||||||
|
@onready var cpu := get_parent() as CPU
|
||||||
|
|
||||||
|
func memory_setup() -> void:
|
||||||
|
var register_types : Dictionary[int, String]
|
||||||
|
for module in cpu.modules:
|
||||||
|
register_types.assign(module.get_register_types())
|
||||||
|
|
||||||
|
for i in range(cpu.register_size):
|
||||||
|
var entry := memory_entry.instantiate() as Control
|
||||||
|
(entry.get_node("address") as Label).text = "[ /" + str(i).pad_zeros(2) + " ]"
|
||||||
|
(entry.get_node("value") as SpinBox).value = 0
|
||||||
|
(entry.get_node("type") as Label).text = register_types[i] if register_types.has(i) else "Free"
|
||||||
|
memory.add_child(entry)
|
||||||
|
|
||||||
|
func _process(_delta: float) -> void:
|
||||||
|
# Set execution indicator
|
||||||
|
for line in code_editor.get_executing_lines():
|
||||||
|
code_editor.set_line_as_executing(line, false)
|
||||||
|
if cpu.cobor_vm.get_program_size() < cpu.cobor_vm.get_program_counter():
|
||||||
|
code_editor.set_line_as_executing(cpu.cobor_vm.get_program_counter(), true)
|
||||||
|
# Show register values
|
||||||
|
var registers := cpu.cobor_vm.get_registers()
|
||||||
|
for i in range(registers.size()):
|
||||||
|
var entry := memory.get_child(i) as Control
|
||||||
|
(entry.get_node("value") as SpinBox).value = registers[i]
|
||||||
|
|
||||||
|
func _on_compile_button_pressed() -> void:
|
||||||
|
cpu.compile_code(code_editor.text)
|
||||||
|
|
||||||
|
func _on_stop_button_pressed() -> void:
|
||||||
|
code_editor.editable = true
|
||||||
|
cpu.stop()
|
||||||
|
|
||||||
|
func _on_play_button_pressed() -> void:
|
||||||
|
if code_editor.editable:
|
||||||
|
cpu.compile_code(code_editor.text)
|
||||||
|
code_editor.editable = false
|
||||||
|
cpu.run()
|
||||||
|
|
||||||
|
func _on_pause_button_pressed() -> void:
|
||||||
|
cpu.pause()
|
||||||
|
|
||||||
|
func _on_step_button_pressed() -> void:
|
||||||
|
if code_editor.editable:
|
||||||
|
cpu.compile_code(code_editor.text)
|
||||||
|
code_editor.editable = false
|
||||||
|
cpu.run_step()
|
||||||
1
nodes/robots/coding/programming_ui.gd.uid
Normal file
1
nodes/robots/coding/programming_ui.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://csub2er5wvqj3
|
||||||
82
nodes/robots/coding/programming_ui.tscn
Normal file
82
nodes/robots/coding/programming_ui.tscn
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://c2es6v8lb8tug"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://csub2er5wvqj3" path="res://nodes/robots/coding/programming_ui.gd" id="1_qk3c3"]
|
||||||
|
|
||||||
|
[node name="ProgrammingUI" type="PanelContainer"]
|
||||||
|
anchors_preset = 9
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = 314.0
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_qk3c3")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Programming"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = " Source Code "
|
||||||
|
|
||||||
|
[node name="Code" type="CodeEdit" parent="VBoxContainer/HBoxContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
placeholder_text = "Code here..."
|
||||||
|
symbol_tooltip_on_hover = true
|
||||||
|
gutters_draw_executing_lines = true
|
||||||
|
gutters_draw_line_numbers = true
|
||||||
|
gutters_zero_pad_line_numbers = true
|
||||||
|
indent_automatic = true
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
horizontal_scroll_mode = 0
|
||||||
|
|
||||||
|
[node name="Memory" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/ScrollContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="compileButton" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "[C]"
|
||||||
|
|
||||||
|
[node name="StopButton" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "[ ]"
|
||||||
|
|
||||||
|
[node name="PlayButton" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = ">"
|
||||||
|
|
||||||
|
[node name="PauseButton" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "||"
|
||||||
|
|
||||||
|
[node name="StepButton" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = ">|"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/compileButton" to="." method="_on_compile_button_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/StopButton" to="." method="_on_stop_button_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/PlayButton" to="." method="_on_play_button_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/PauseButton" to="." method="_on_pause_button_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/StepButton" to="." method="_on_step_button_pressed"]
|
||||||
15
nodes/robots/modules/module.gd
Normal file
15
nodes/robots/modules/module.gd
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
class_name Module extends Node
|
||||||
|
|
||||||
|
@onready var cpu := get_parent() as CPU
|
||||||
|
|
||||||
|
func get_register_reservation_size()->int:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func set_reserved_registers(index:int)->void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func get_register_types()->Dictionary[int, String]:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
func late_tick()->void:
|
||||||
|
pass
|
||||||
1
nodes/robots/modules/module.gd.uid
Normal file
1
nodes/robots/modules/module.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://duhvogscwatf6
|
||||||
75
nodes/robots/modules/path_finder_module.gd
Normal file
75
nodes/robots/modules/path_finder_module.gd
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
extends Module
|
||||||
|
|
||||||
|
var enabled := true
|
||||||
|
|
||||||
|
var pos_x_register_index:int
|
||||||
|
var pos_y_register_index:int
|
||||||
|
var pos_z_register_index:int
|
||||||
|
var index_register_index:int
|
||||||
|
|
||||||
|
var prev_index := 0
|
||||||
|
var target := Vector3i.ZERO
|
||||||
|
var path : Array[Vector3i]
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if Terrain.instance == null:
|
||||||
|
print("No terrain to plan path on")
|
||||||
|
if cpu.get_parent() is not Robot:
|
||||||
|
print("Module not part of Robot")
|
||||||
|
|
||||||
|
func get_register_reservation_size()->int:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
func set_reserved_registers(index:int)->void:
|
||||||
|
pos_x_register_index = index
|
||||||
|
pos_y_register_index = index+1
|
||||||
|
pos_z_register_index = index+2
|
||||||
|
index_register_index = index+3
|
||||||
|
|
||||||
|
func get_register_types()->Dictionary[int, String]:
|
||||||
|
return {
|
||||||
|
pos_x_register_index: "[X] Path",
|
||||||
|
pos_y_register_index: "[Y] Path",
|
||||||
|
pos_z_register_index: "[Z] Path",
|
||||||
|
index_register_index: "Idx Path"
|
||||||
|
}
|
||||||
|
|
||||||
|
func early_tick()->void:
|
||||||
|
var registers := cpu.cobor_vm.get_registers()
|
||||||
|
prev_index = registers[index_register_index]
|
||||||
|
|
||||||
|
func late_tick()->void:
|
||||||
|
var registers := cpu.cobor_vm.get_registers()
|
||||||
|
var index := registers[index_register_index]
|
||||||
|
if index < 0:
|
||||||
|
target = Vector3i(
|
||||||
|
registers[pos_x_register_index],
|
||||||
|
registers[pos_y_register_index],
|
||||||
|
registers[pos_z_register_index]
|
||||||
|
)
|
||||||
|
print("Target set: ", target)
|
||||||
|
else:
|
||||||
|
if index == prev_index:
|
||||||
|
print("index stays same")
|
||||||
|
return
|
||||||
|
if prev_index < 0:
|
||||||
|
var path_finder := VoxelAStarGrid3D.new()
|
||||||
|
path_finder.set_terrain(Terrain.instance)
|
||||||
|
path_finder.set_region(AABB(cpu.get_parent().global_position + Vector3.ONE * -100, Vector3.ONE * 200))
|
||||||
|
path = path_finder.find_path(cpu.get_parent().global_position, target)
|
||||||
|
if not path.is_empty():
|
||||||
|
path.append(target)
|
||||||
|
print("Recalculating path of size:", path.size(), " towards: ", target)
|
||||||
|
if index >= path.size():
|
||||||
|
index = path.size()-1
|
||||||
|
var step:Vector3i
|
||||||
|
if path.size() == 0:
|
||||||
|
step = Vector3i.ZERO
|
||||||
|
else:
|
||||||
|
step = path[index]
|
||||||
|
print("next step: ", step)
|
||||||
|
registers[pos_x_register_index] = step.x
|
||||||
|
registers[pos_y_register_index] = step.y
|
||||||
|
registers[pos_z_register_index] = step.z
|
||||||
|
registers[index_register_index] = index
|
||||||
|
cpu.cobor_vm.set_registers(cpu.register_size, registers)
|
||||||
1
nodes/robots/modules/path_finder_module.gd.uid
Normal file
1
nodes/robots/modules/path_finder_module.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://wsrudejqfo5e
|
||||||
52
nodes/robots/modules/player_click_module.gd
Normal file
52
nodes/robots/modules/player_click_module.gd
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
extends Module
|
||||||
|
|
||||||
|
var enabled := true
|
||||||
|
|
||||||
|
var pos_x_register_index:int
|
||||||
|
var pos_y_register_index:int
|
||||||
|
var pos_z_register_index:int
|
||||||
|
|
||||||
|
var pos := Vector3i.ZERO
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if Terrain.instance == null:
|
||||||
|
print("No terrain to get clicks from")
|
||||||
|
|
||||||
|
func get_register_reservation_size()->int:
|
||||||
|
return 3
|
||||||
|
|
||||||
|
func set_reserved_registers(index:int)->void:
|
||||||
|
pos_x_register_index = index
|
||||||
|
pos_y_register_index = index+1
|
||||||
|
pos_z_register_index = index+2
|
||||||
|
|
||||||
|
func get_register_types()->Dictionary[int, String]:
|
||||||
|
return {
|
||||||
|
pos_x_register_index: "[X] Click",
|
||||||
|
pos_y_register_index: "[Y] Click",
|
||||||
|
pos_z_register_index: "[Z] Click"
|
||||||
|
}
|
||||||
|
|
||||||
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if not enabled: return
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
var button_event = event as InputEventMouseButton
|
||||||
|
if button_event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
set_click_registers()
|
||||||
|
elif button_event.button_index == MOUSE_BUTTON_RIGHT:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_click_registers()->void:
|
||||||
|
var mouse_pos_2d := get_viewport().get_mouse_position()
|
||||||
|
var current_camera := get_viewport().get_camera_3d()
|
||||||
|
var origin := current_camera.project_ray_origin(mouse_pos_2d)
|
||||||
|
var dir := current_camera.project_ray_normal(mouse_pos_2d)
|
||||||
|
var res := Terrain.instance.get_voxel_tool().raycast(origin, dir, 100)
|
||||||
|
pos = res.previous_position
|
||||||
|
|
||||||
|
func early_tick()->void:
|
||||||
|
var registers := cpu.cobor_vm.get_registers()
|
||||||
|
registers[pos_x_register_index] = pos.x
|
||||||
|
registers[pos_y_register_index] = pos.y
|
||||||
|
registers[pos_z_register_index] = pos.z
|
||||||
|
cpu.cobor_vm.set_registers(cpu.register_size, registers)
|
||||||
1
nodes/robots/modules/player_click_module.gd.uid
Normal file
1
nodes/robots/modules/player_click_module.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dii2n2xcatyuh
|
||||||
57
nodes/robots/robot.gd
Normal file
57
nodes/robots/robot.gd
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
class_name Robot extends CharacterBody3D
|
||||||
|
|
||||||
|
@onready var terrain := get_node("../VoxelTerrain") as VoxelTerrain
|
||||||
|
|
||||||
|
var selected := false
|
||||||
|
var path : Array[Vector3i]
|
||||||
|
|
||||||
|
func _on_input_event(camera: Node, event: InputEvent, event_position: Vector3, normal: Vector3, shape_idx: int) -> void:
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
var button_event = event as InputEventMouseButton
|
||||||
|
if button_event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
$CPU.show_ui(true)
|
||||||
|
selected = true
|
||||||
|
elif button_event.button_index == MOUSE_BUTTON_RIGHT:
|
||||||
|
$CPU.show_ui(false)
|
||||||
|
selected = false
|
||||||
|
|
||||||
|
#func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
#if selected:
|
||||||
|
#if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
#var button_event = event as InputEventMouseButton
|
||||||
|
#if button_event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
#move_to_mouse_click()
|
||||||
|
#elif button_event.button_index == MOUSE_BUTTON_RIGHT:
|
||||||
|
#pass
|
||||||
|
|
||||||
|
func move_to_mouse_click():
|
||||||
|
var mouse_pos_2d := get_viewport().get_mouse_position()
|
||||||
|
var current_camera := get_viewport().get_camera_3d()
|
||||||
|
var origin := current_camera.project_ray_origin(mouse_pos_2d)
|
||||||
|
var dir := current_camera.project_ray_normal(mouse_pos_2d)
|
||||||
|
var res := terrain.get_voxel_tool().raycast(origin, dir, 100)
|
||||||
|
var path_finder := VoxelAStarGrid3D.new()
|
||||||
|
path_finder.set_terrain(terrain)
|
||||||
|
path_finder.set_region(AABB(Vector3.ONE * -100, Vector3.ONE * 200))
|
||||||
|
path = path_finder.find_path(Vector3i(global_position), res.previous_position)
|
||||||
|
if not path.is_empty():
|
||||||
|
path.append(res.previous_position)
|
||||||
|
for step in path:
|
||||||
|
print(step)
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if not path.is_empty():
|
||||||
|
var next_position := Vector3(path[0]) + Vector3.ONE * 0.5;
|
||||||
|
if path.size() == 1:
|
||||||
|
if next_position.distance_to(global_position) < 0.1:
|
||||||
|
rotation.x = 0
|
||||||
|
rotation.y = round(rotation.y/(PI/2))*PI/2
|
||||||
|
rotation.z = 0
|
||||||
|
print("arrived")
|
||||||
|
if next_position.distance_to(global_position) < 0.1:
|
||||||
|
global_position = next_position
|
||||||
|
path.remove_at(0)
|
||||||
|
else:
|
||||||
|
look_at(next_position)
|
||||||
|
velocity = (next_position - global_position).normalized() * 5
|
||||||
|
move_and_slide()
|
||||||
1
nodes/robots/robot.gd.uid
Normal file
1
nodes/robots/robot.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bnw0h8cuyf3g5
|
||||||
48
nodes/robots/robot.tscn
Normal file
48
nodes/robots/robot.tscn
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[gd_scene load_steps=10 format=3 uid="uid://chem70rrdwjpg"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://bnw0h8cuyf3g5" path="res://nodes/robots/robot.gd" id="1_suikl"]
|
||||||
|
[ext_resource type="Script" uid="uid://dii2n2xcatyuh" path="res://nodes/robots/modules/player_click_module.gd" id="3_tmdoi"]
|
||||||
|
[ext_resource type="Script" uid="uid://wsrudejqfo5e" path="res://nodes/robots/modules/path_finder_module.gd" id="4_hm8dm"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://crtis0eyywl61" path="res://nodes/robots/coding/cpu.tscn" id="5_r4wpy"]
|
||||||
|
|
||||||
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_hm8dm"]
|
||||||
|
albedo_color = Color(0, 0.52959, 0.856942, 1)
|
||||||
|
|
||||||
|
[sub_resource type="BoxMesh" id="BoxMesh_hm8dm"]
|
||||||
|
material = SubResource("StandardMaterial3D_hm8dm")
|
||||||
|
size = Vector3(1, 0.9, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r4wpy"]
|
||||||
|
albedo_color = Color(1, 0.447059, 0, 1)
|
||||||
|
|
||||||
|
[sub_resource type="PrismMesh" id="PrismMesh_hm8dm"]
|
||||||
|
material = SubResource("StandardMaterial3D_r4wpy")
|
||||||
|
size = Vector3(0.4, 0.7, 0.1)
|
||||||
|
|
||||||
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_llm6e"]
|
||||||
|
radius = 0.4
|
||||||
|
height = 0.8
|
||||||
|
|
||||||
|
[node name="Robot" type="CharacterBody3D"]
|
||||||
|
script = ExtResource("1_suikl")
|
||||||
|
|
||||||
|
[node name="CPU" parent="." instance=ExtResource("5_r4wpy")]
|
||||||
|
|
||||||
|
[node name="PlayerClickModule" type="Node" parent="CPU"]
|
||||||
|
script = ExtResource("3_tmdoi")
|
||||||
|
|
||||||
|
[node name="PathFinderModule" type="Node" parent="CPU"]
|
||||||
|
script = ExtResource("4_hm8dm")
|
||||||
|
|
||||||
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0)
|
||||||
|
mesh = SubResource("BoxMesh_hm8dm")
|
||||||
|
|
||||||
|
[node name="MeshInstance3D2" type="MeshInstance3D" parent="MeshInstance3D"]
|
||||||
|
transform = Transform3D(1, -1.31134e-07, 4.37114e-08, -4.37114e-08, -4.37114e-08, 1, -1.31134e-07, -1, -4.37114e-08, 0, 0.5, 0)
|
||||||
|
mesh = SubResource("PrismMesh_hm8dm")
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
|
shape = SubResource("CapsuleShape3D_llm6e")
|
||||||
|
|
||||||
|
[connection signal="input_event" from="." to="." method="_on_input_event"]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[gd_resource type="VoxelBlockyLibrary" load_steps=4 format=3 uid="uid://bsue4rd3wdfsl"]
|
[gd_resource type="VoxelBlockyLibrary" load_steps=4 format=3 uid="uid://bsue4rd3wdfsl"]
|
||||||
|
|
||||||
[ext_resource type="Material" uid="uid://de6s8en5fcyyw" path="res://BlockMaterial.tres" id="1_evy8o"]
|
[ext_resource type="Material" uid="uid://de6s8en5fcyyw" path="res://nodes/world/BlockMaterial.tres" id="1_evy8o"]
|
||||||
|
|
||||||
[sub_resource type="VoxelBlockyModelEmpty" id="VoxelBlockyModelEmpty_o5qli"]
|
[sub_resource type="VoxelBlockyModelEmpty" id="VoxelBlockyModelEmpty_o5qli"]
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://de6s8en5fcyyw"]
|
[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://de6s8en5fcyyw"]
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://bcctuptks33yd" path="res://blocky_game_atlas.webp" id="1_nmlo6"]
|
[ext_resource type="Texture2D" uid="uid://bcctuptks33yd" path="res://nodes/world/blocky_game_atlas.webp" id="1_nmlo6"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
albedo_texture = ExtResource("1_nmlo6")
|
albedo_texture = ExtResource("1_nmlo6")
|
||||||
6
nodes/world/Terrain.gd
Normal file
6
nodes/world/Terrain.gd
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class_name Terrain extends VoxelTerrain
|
||||||
|
|
||||||
|
static var instance:Terrain
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
instance = self
|
||||||
1
nodes/world/Terrain.gd.uid
Normal file
1
nodes/world/Terrain.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cp4pflpo7neyq
|
||||||
51
nodes/world/TerrainScene.tscn
Normal file
51
nodes/world/TerrainScene.tscn
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
[gd_scene load_steps=12 format=3 uid="uid://bp6ewa3urgac8"]
|
||||||
|
|
||||||
|
[ext_resource type="VoxelBlockyLibrary" uid="uid://bsue4rd3wdfsl" path="res://nodes/world/BlockLibrary.tres" id="1_4rm5p"]
|
||||||
|
[ext_resource type="Material" uid="uid://de6s8en5fcyyw" path="res://nodes/world/BlockMaterial.tres" id="2_yirul"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ddyulj4dsrkms" path="res://nodes/world/terrain_editor.tscn" id="3_heupn"]
|
||||||
|
[ext_resource type="Script" uid="uid://cp4pflpo7neyq" path="res://nodes/world/Terrain.gd" id="3_yirul"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cy0nvmw51bwof" path="res://nodes/camera/controllable_camera.tscn" id="4_ublpu"]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_gadlc"]
|
||||||
|
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||||
|
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_t8uwy"]
|
||||||
|
sky_material = SubResource("ProceduralSkyMaterial_gadlc")
|
||||||
|
|
||||||
|
[sub_resource type="Environment" id="Environment_5g68j"]
|
||||||
|
background_mode = 2
|
||||||
|
sky = SubResource("Sky_t8uwy")
|
||||||
|
|
||||||
|
[sub_resource type="FastNoiseLite" id="FastNoiseLite_v3kfg"]
|
||||||
|
|
||||||
|
[sub_resource type="VoxelGeneratorNoise2D" id="VoxelGeneratorNoise2D_mko3u"]
|
||||||
|
channel = 0
|
||||||
|
height_start = 0.0
|
||||||
|
height_range = 20.0
|
||||||
|
noise = SubResource("FastNoiseLite_v3kfg")
|
||||||
|
|
||||||
|
[sub_resource type="VoxelMesherBlocky" id="VoxelMesherBlocky_3tbtj"]
|
||||||
|
library = ExtResource("1_4rm5p")
|
||||||
|
|
||||||
|
[node name="VoxelWorld" type="Node"]
|
||||||
|
|
||||||
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
|
environment = SubResource("Environment_5g68j")
|
||||||
|
|
||||||
|
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||||
|
transform = Transform3D(-0.866024, -0.433016, 0.250001, 0, 0.499998, 0.866026, -0.500003, 0.749999, -0.43301, 0, 0, 0)
|
||||||
|
shadow_enabled = true
|
||||||
|
|
||||||
|
[node name="VoxelTerrain" type="VoxelTerrain" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0)
|
||||||
|
generator = SubResource("VoxelGeneratorNoise2D_mko3u")
|
||||||
|
mesher = SubResource("VoxelMesherBlocky_3tbtj")
|
||||||
|
bounds = AABB(-1040, -32, -1040, 2080, 96, 2080)
|
||||||
|
material_override = ExtResource("2_yirul")
|
||||||
|
script = ExtResource("3_yirul")
|
||||||
|
|
||||||
|
[node name="TerrainEditor" parent="VoxelTerrain" instance=ExtResource("3_heupn")]
|
||||||
|
|
||||||
|
[node name="ControllableCamera" parent="." instance=ExtResource("4_ublpu")]
|
||||||
|
transform = Transform3D(-0.61081, -0.620921, 0.491291, 0, 0.620492, 0.784213, -0.791777, 0.479005, -0.379003, 34.4662, 28.9798, -20.4)
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -3,7 +3,7 @@
|
|||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://bcctuptks33yd"
|
uid="uid://bcctuptks33yd"
|
||||||
path.s3tc="res://.godot/imported/blocky_game_atlas.webp-aa4a7bf0424ced14ddb4e0a3548a39f2.s3tc.ctex"
|
path.s3tc="res://.godot/imported/blocky_game_atlas.webp-23ee11425f1b691f850e88290909a9fb.s3tc.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc_bptc"],
|
"imported_formats": ["s3tc_bptc"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
@@ -11,8 +11,8 @@ metadata={
|
|||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://blocky_game_atlas.webp"
|
source_file="res://nodes/world/blocky_game_atlas.webp"
|
||||||
dest_files=["res://.godot/imported/blocky_game_atlas.webp-aa4a7bf0424ced14ddb4e0a3548a39f2.s3tc.ctex"]
|
dest_files=["res://.godot/imported/blocky_game_atlas.webp-23ee11425f1b691f850e88290909a9fb.s3tc.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
32
nodes/world/terrain_editor.gd
Normal file
32
nodes/world/terrain_editor.gd
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
@onready var voxelTool := (get_parent() as VoxelTerrain).get_voxel_tool()
|
||||||
|
|
||||||
|
var block_edit := false
|
||||||
|
|
||||||
|
func _unhandled_input(event):
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
if block_edit:
|
||||||
|
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
perform_block_action(true)
|
||||||
|
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||||
|
get_tree().create_timer(0.15).timeout.connect(
|
||||||
|
func():
|
||||||
|
if not Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
|
||||||
|
perform_block_action(false)
|
||||||
|
)
|
||||||
|
|
||||||
|
func perform_block_action(add_block:bool)->void:
|
||||||
|
var mouse_pos_2d := get_viewport().get_mouse_position()
|
||||||
|
var current_camera := get_viewport().get_camera_3d()
|
||||||
|
var origin := current_camera.project_ray_origin(mouse_pos_2d)
|
||||||
|
var dir := current_camera.project_ray_normal(mouse_pos_2d)
|
||||||
|
var res := voxelTool.raycast(origin, dir, 50)
|
||||||
|
if res != null:
|
||||||
|
if add_block:
|
||||||
|
voxelTool.set_voxel(res.previous_position, 1)
|
||||||
|
else:
|
||||||
|
voxelTool.set_voxel(res.position, 0)
|
||||||
|
|
||||||
|
func _on_button_toggled(toggled_on: bool) -> void:
|
||||||
|
block_edit = toggled_on
|
||||||
1
nodes/world/terrain_editor.gd.uid
Normal file
1
nodes/world/terrain_editor.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://vnjdiql72brq
|
||||||
18
nodes/world/terrain_editor.tscn
Normal file
18
nodes/world/terrain_editor.tscn
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://ddyulj4dsrkms"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://vnjdiql72brq" path="res://nodes/world/terrain_editor.gd" id="1_6evft"]
|
||||||
|
|
||||||
|
[node name="TerrainEditor" type="Node"]
|
||||||
|
script = ExtResource("1_6evft")
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="."]
|
||||||
|
anchors_preset = 1
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_left = -84.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
toggle_mode = true
|
||||||
|
text = "Block Edit"
|
||||||
|
|
||||||
|
[connection signal="toggled" from="Button" to="." method="_on_button_toggled"]
|
||||||
@@ -11,6 +11,55 @@ config_version=5
|
|||||||
[application]
|
[application]
|
||||||
|
|
||||||
config/name="Cobor"
|
config/name="Cobor"
|
||||||
run/main_scene="uid://7q00x01xdsal"
|
run/main_scene="uid://d0b7m4vykcfy2"
|
||||||
config/features=PackedStringArray("4.4")
|
config/features=PackedStringArray("4.4")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[filesystem]
|
||||||
|
|
||||||
|
import/blender/enabled=false
|
||||||
|
|
||||||
|
[importer_defaults]
|
||||||
|
|
||||||
|
scene={
|
||||||
|
"_subresources": {},
|
||||||
|
"animation/fps": 30,
|
||||||
|
"animation/import": true,
|
||||||
|
"animation/import_rest_as_RESET": false,
|
||||||
|
"animation/remove_immutable_tracks": true,
|
||||||
|
"animation/trimming": false,
|
||||||
|
"gltf/embedded_image_handling": 0,
|
||||||
|
"gltf/naming_version": 1,
|
||||||
|
"import_script/path": "",
|
||||||
|
"meshes/create_shadow_meshes": true,
|
||||||
|
"meshes/ensure_tangents": true,
|
||||||
|
"meshes/force_disable_compression": false,
|
||||||
|
"meshes/generate_lods": true,
|
||||||
|
"meshes/light_baking": 1,
|
||||||
|
"meshes/lightmap_texel_size": 0.2,
|
||||||
|
"nodes/apply_root_scale": true,
|
||||||
|
"nodes/import_as_skeleton_bones": false,
|
||||||
|
"nodes/root_name": "",
|
||||||
|
"nodes/root_scale": 1.0,
|
||||||
|
"nodes/root_type": "",
|
||||||
|
"nodes/use_node_type_suffixes": true,
|
||||||
|
"skins/use_named_skins": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
camera_control={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(127, 25),"global_position":Vector2(136, 73),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
left_click={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(229, 14),"global_position":Vector2(238, 62),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
right_click={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(61, 10),"global_position":Vector2(70, 58),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
8
resources/cobor_script/prog1.txt
Normal file
8
resources/cobor_script/prog1.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
set -1 /7
|
||||||
|
mov /1 /4
|
||||||
|
mov /2 /5
|
||||||
|
mov /3 /6
|
||||||
|
set 0 /7
|
||||||
|
set 1 /7
|
||||||
|
set 2 /7
|
||||||
|
set 3 /7
|
||||||
154
scenes/main.tscn
154
scenes/main.tscn
@@ -1,154 +0,0 @@
|
|||||||
[gd_scene load_steps=11 format=3 uid="uid://7q00x01xdsal"]
|
|
||||||
|
|
||||||
[ext_resource type="VoxelBlockyLibrary" uid="uid://bsue4rd3wdfsl" path="res://BlockLibrary.tres" id="1_0wfyh"]
|
|
||||||
[ext_resource type="Material" uid="uid://de6s8en5fcyyw" path="res://BlockMaterial.tres" id="1_o5qli"]
|
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_o5qli"]
|
|
||||||
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
|
||||||
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
|
||||||
|
|
||||||
[sub_resource type="Sky" id="Sky_0wfyh"]
|
|
||||||
sky_material = SubResource("ProceduralSkyMaterial_o5qli")
|
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment_sugp2"]
|
|
||||||
background_mode = 2
|
|
||||||
sky = SubResource("Sky_0wfyh")
|
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o5qli"]
|
|
||||||
albedo_color = Color(0.313808, 0.455394, 0.721014, 1)
|
|
||||||
|
|
||||||
[sub_resource type="BoxMesh" id="BoxMesh_o5qli"]
|
|
||||||
material = SubResource("StandardMaterial3D_o5qli")
|
|
||||||
|
|
||||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_sgp6g"]
|
|
||||||
|
|
||||||
[sub_resource type="VoxelGeneratorNoise2D" id="VoxelGeneratorNoise2D_o5qli"]
|
|
||||||
channel = 0
|
|
||||||
height_start = 0.0
|
|
||||||
height_range = 20.0
|
|
||||||
noise = SubResource("FastNoiseLite_sgp6g")
|
|
||||||
|
|
||||||
[sub_resource type="VoxelMesherBlocky" id="VoxelMesherBlocky_tefeu"]
|
|
||||||
library = ExtResource("1_0wfyh")
|
|
||||||
|
|
||||||
[node name="Main" type="Node"]
|
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
|
||||||
environment = SubResource("Environment_sugp2")
|
|
||||||
|
|
||||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
|
||||||
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
|
|
||||||
shadow_enabled = true
|
|
||||||
|
|
||||||
[node name="Robot" type="Node3D" parent="."]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.5, 14, 2.5)
|
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Robot"]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
|
|
||||||
mesh = SubResource("BoxMesh_o5qli")
|
|
||||||
|
|
||||||
[node name="Camera3D" type="Camera3D" parent="Robot"]
|
|
||||||
transform = Transform3D(-0.996038, -0.0493504, 0.0739856, 0, 0.831912, 0.554908, -0.0889344, 0.552709, -0.828616, 0.617269, 2.49481, -3.59337)
|
|
||||||
|
|
||||||
[node name="VoxelViewer" type="VoxelViewer" parent="Robot/Camera3D"]
|
|
||||||
|
|
||||||
[node name="Control" type="PanelContainer" parent="."]
|
|
||||||
anchors_preset = 9
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_right = 227.0
|
|
||||||
grow_vertical = 2
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="Control"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Programming"
|
|
||||||
horizontal_alignment = 1
|
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="Control/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
size_flags_vertical = 3
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="Control/VBoxContainer/HBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer/HBoxContainer/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = " Source Code "
|
|
||||||
|
|
||||||
[node name="CodeEdit" type="CodeEdit" parent="Control/VBoxContainer/HBoxContainer/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
size_flags_vertical = 3
|
|
||||||
text = "Move #1 0
|
|
||||||
"
|
|
||||||
|
|
||||||
[node name="ItemList" type="VBoxContainer" parent="Control/VBoxContainer/HBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="Control/VBoxContainer/HBoxContainer/ItemList"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "#0"
|
|
||||||
|
|
||||||
[node name="SpinBox" type="SpinBox" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="HBoxContainer2" type="HBoxContainer" parent="Control/VBoxContainer/HBoxContainer/ItemList"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "#1"
|
|
||||||
|
|
||||||
[node name="SpinBox" type="SpinBox" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="HBoxContainer3" type="HBoxContainer" parent="Control/VBoxContainer/HBoxContainer/ItemList"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer3"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "#2"
|
|
||||||
|
|
||||||
[node name="SpinBox" type="SpinBox" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer3"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="HBoxContainer4" type="HBoxContainer" parent="Control/VBoxContainer/HBoxContainer/ItemList"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer4"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "#3"
|
|
||||||
|
|
||||||
[node name="SpinBox" type="SpinBox" parent="Control/VBoxContainer/HBoxContainer/ItemList/HBoxContainer4"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="HBoxContainer2" type="HBoxContainer" parent="Control/VBoxContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
alignment = 1
|
|
||||||
|
|
||||||
[node name="StopButton" type="Button" parent="Control/VBoxContainer/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Stop"
|
|
||||||
|
|
||||||
[node name="PlayButton" type="Button" parent="Control/VBoxContainer/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Play"
|
|
||||||
|
|
||||||
[node name="PauseButton" type="Button" parent="Control/VBoxContainer/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Pause"
|
|
||||||
|
|
||||||
[node name="StepButton" type="Button" parent="Control/VBoxContainer/HBoxContainer2"]
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Step"
|
|
||||||
|
|
||||||
[node name="VoxelTerrain" type="VoxelTerrain" parent="."]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0)
|
|
||||||
generator = SubResource("VoxelGeneratorNoise2D_o5qli")
|
|
||||||
mesher = SubResource("VoxelMesherBlocky_tefeu")
|
|
||||||
bounds = AABB(-1040, -32, -1040, 2080, 96, 2080)
|
|
||||||
material_override = ExtResource("1_o5qli")
|
|
||||||
Reference in New Issue
Block a user