25 Commits

Author SHA1 Message Date
d5d27418d1 Fix missing extension on windows build artifacts 2023-08-17 14:19:33 +02:00
401dda3f8e Only run builds on push to master or pull requests 2023-08-17 13:42:22 +02:00
17b62e096b Move config file to separate workflot step 2023-08-17 13:32:04 +02:00
8e758b3069 Add example config to build artifacts 2023-08-17 13:20:19 +02:00
45f849a7cf Bump Godot Build Action to 1.5.0 2023-08-17 13:01:32 +02:00
efe5805e6e Add Github Build Workflow 2023-08-17 12:53:42 +02:00
16e7f2185e Add build directories 2023-08-17 12:52:49 +02:00
1693616643 Add export presets to repo 2023-08-17 12:42:00 +02:00
36344fb2cb Poll while fetching remote sources to avoid timeout
If we don't respond to pings for too long, Jose considers us dead.
That becomes a problem when fetching large resources or from a slow remote
2023-08-07 17:29:36 +02:00
0e71f372c3 Cleanup file and folder structure 2023-08-07 10:38:53 +02:00
879e494840 Fix loading of fallback image in exported builds 2023-08-05 13:25:19 +02:00
dfbbea1903 Add all build folders to gitignore 2023-08-02 23:21:42 +02:00
07e72dc755 Fix getting stuck on reconnect if the first attempt fails
also added the hostname to the register request
2023-08-02 23:20:51 +02:00
60fdbf9557 Return fallback image if remote fetch fails 2023-08-02 23:16:20 +02:00
1210d76381 Use device type if username is unavailable 2023-07-31 17:15:24 +02:00
d7d8dff736 Add timeout to handle close and add missing cfg template
Also adds the reno icon
2023-07-31 16:56:07 +02:00
c84c79d966 Extend debug output 2023-07-31 16:43:28 +02:00
7acc8c5ee3 Replace placeholder strings in labels (debug requests) 2023-07-31 14:58:38 +02:00
25215ea41a Make paths absolute to fix permissions issues
on Android
2023-06-16 11:16:29 +02:00
a939497f1a Implemented direct image data transfer
via websockets to the job-server.
The images are then served by the job-server itself.
2023-06-15 18:01:32 +02:00
847c5753c2 Update README.md 2023-06-14 10:13:43 +02:00
1676bbb886 Implement basic node side image caching 2023-06-12 23:42:25 +02:00
3f2473d7e0 Top align label nodes 2023-06-12 21:25:34 +02:00
95840b1dbf Add positioning for image elements 2023-06-08 10:39:28 +02:00
bbecb77f03 Add auth-key for node registration 2023-06-07 17:23:00 +02:00
22 changed files with 561 additions and 114 deletions

42
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Build Godot Project
on:
push:
branches:
- master
pull_request:
types: [opened, reopened]
jobs:
Godot:
runs-on: ubuntu-latest
strategy:
matrix:
platform:
- name: linux
extension:
- name : windows
extension: .exe
steps:
- uses: actions/checkout@v2
with:
lfs: true
- name: Build
id: build
uses: manleydev/build-godot-action@v1.5.0
with:
name: reno${{ matrix.platform.extension }}
preset: ${{ matrix.platform.name }}
debugMode: "true"
- name: Upload Build Artifact
uses: actions/upload-artifact@v2
with:
name: TohoReno-${{ matrix.platform.name }}
path: |
${{ github.workspace }}/${{ steps.build.outputs.build }}
- name: Upload Example Config Artifact
uses: actions/upload-artifact@v2
with:
name: TohoReno-${{ matrix.platform.name }}
path: |
${{ github.workspace }}/example-config.cfg

5
.gitignore vendored
View File

@@ -1,12 +1,13 @@
### Godot ###
# Godot 4+ specific ignores
.godot/
/[Bb]uild/
/[Bb]uilds/
*_build/
/[Oo]utput/
/[Cc]ache/
# Godot-specific ignores
.import/
export.cfg
export_presets.cfg
config.cgf
# Imported translations (automatically generated from CSV files)

View File

@@ -1,61 +0,0 @@
extends HTTPRequest
var socket = WebSocketPeer.new()
func InitWebsocket():
print("Connecting websocket ")
socket.connect_to_url($"/root/Main".websocket_url, TLSOptions.client_unsafe())
while socket.get_ready_state() != WebSocketPeer.STATE_OPEN:
socket.poll()
socket.send_text(str({"register": 1}))
print("Connected")
while true:
await PollWebsocket()
RenderingServer.force_draw()
DisplayServer.process_events()
func PollWebsocket():
var main = $"/root/Main"
socket.poll()
var state = socket.get_ready_state()
if state == WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
var packet = socket.get_packet()
var json = JSON.parse_string(packet.get_string_from_utf8())
print("Packet: ", packet.slice(0,5), "...")
if "welcome" in json:
print("Registered as client %s" % json["welcome"]["clientId"])
if "job" in json:
var job = json["job"]
print("Recevied Job ", job["jobId"])
main.rendering = true
var result = await $"../Renderer".RenderJob(job)
var response = {
"result": {
"jobId": job["jobId"],
"path": $"/root/Main".public_path + result
}
}
socket.send_text(str(response))
print("Sent result ", result)
main.rendering = false
elif state == WebSocketPeer.STATE_CLOSING:
# Keep polling to achieve proper close.
pass
elif state == WebSocketPeer.STATE_CLOSED:
var code = socket.get_close_code()
var reason = socket.get_close_reason()
print("WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != -1])
print("Attempting reconnect in 10")
set_process(false) # Stop processing.
await get_tree().create_timer(10).timeout
InitWebsocket()
func _process(_delta):
pass

View File

@@ -1,2 +1,4 @@
![reno-banner](https://github.com/JanGross/toho-reno/assets/13641301/cdbd1d80-4426-4b51-ac6b-e1fb1836f82f)
## Render node for Toho Miku!
Takes render jobs from [Toho-Jose](https://github.com/jangross/toho-jose) and returns a URL pointing to the rendered asset.

View File

@@ -1,19 +0,0 @@
extends HTTPRequest
func GetRemoteImage(url):
var image = Image.new()
print("Fetching remote image %s" % url)
request(url)
var res = await request_completed
var magicBytes = res[3].slice(0,8)
print(magicBytes)
var error = null
if magicBytes == PackedByteArray([137, 80, 78, 71, 13, 10, 26, 10]):
print("Detected PNG File")
error = image.load_png_from_buffer(res[3])
if magicBytes == PackedByteArray([255, 216, 255, 224, 0, 16, 74, 70]):
print("Detected JPG File")
error = image.load_jpg_from_buffer(res[3])
if error != OK:
print("Error fetching image ", str(error))
return image

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

BIN
assets/fallback_card.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bwf4bqfk3gtax"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
uid="uid://ckte5ibti7d3w"
path="res://.godot/imported/fallback_card.png-33fded034422885f6438964b5fbb84f0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
source_file="res://assets/fallback_card.png"
dest_files=["res://.godot/imported/fallback_card.png-33fded034422885f6438964b5fbb84f0.ctex"]
[params]
@@ -32,6 +32,3 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://skthvfx7pq6m"
path="res://.godot/imported/_e2199ab5-ff42-4ddf-8540-1c16e2d7889f.jpeg-fc56a492e359e0a38ad286972df2992f.ctex"
uid="uid://cxa8l2nu0ycg3"
path="res://.godot/imported/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://_e2199ab5-ff42-4ddf-8540-1c16e2d7889f.jpeg"
dest_files=["res://.godot/imported/_e2199ab5-ff42-4ddf-8540-1c16e2d7889f.jpeg-fc56a492e359e0a38ad286972df2992f.ctex"]
source_file="res://assets/icon.png"
dest_files=["res://.godot/imported/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.ctex"]
[params]

0
builds/android/.gitkeep Normal file
View File

0
builds/linux/.gitkeep Normal file
View File

0
builds/windows/.gitkeep Normal file
View File

View File

@@ -1,4 +1,8 @@
[core]
hostname="default"
auth_key="ay1234"
websocket_url="ws://localhost:6980"
public_path="http://localhost:8899/"
output_dir="./output"
output_dir="user://output"
cache_dir="user://cache"
serve_mode="local"

315
export_presets.cfg Normal file
View File

@@ -0,0 +1,315 @@
[preset.0]
name="linux"
platform="Linux/X11"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="builds/linux/reno.x86_64"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_encryption_key=""
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_script=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
[preset.1]
name="windows"
platform="Windows Desktop"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="builds/windows/reno.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_encryption_key=""
[preset.1.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_script=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/identity_type=0
codesign/identity=""
codesign/password=""
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=false
application/icon=""
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
[preset.2]
name="android"
platform="Android"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter="config.cfg"
exclude_filter=""
export_path="builds/android/reno.apk"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_encryption_key=""
[preset.2.options]
custom_template/debug=""
custom_template/release=""
gradle_build/use_gradle_build=false
gradle_build/export_format=0
gradle_build/min_sdk=""
gradle_build/target_sdk=""
architectures/armeabi-v7a=false
architectures/arm64-v8a=true
architectures/x86=false
architectures/x86_64=false
keystore/debug=""
keystore/debug_user=""
keystore/debug_password=""
keystore/release=""
keystore/release_user=""
keystore/release_password=""
version/code=1
version/name="1.0"
package/unique_name="gg.mnz.toho"
package/name=""
package/signed=true
package/app_category=2
package/retain_data_on_uninstall=false
package/exclude_from_recents=false
launcher_icons/main_192x192="res://icon.png"
launcher_icons/adaptive_foreground_432x432=""
launcher_icons/adaptive_background_432x432=""
graphics/opengl_debug=false
xr_features/xr_mode=0
xr_features/hand_tracking=0
xr_features/hand_tracking_frequency=0
xr_features/passthrough=0
screen/immersive_mode=false
screen/support_small=true
screen/support_normal=true
screen/support_large=true
screen/support_xlarge=true
user_data_backup/allow=false
command_line/extra_args=""
apk_expansion/enable=false
apk_expansion/SALT=""
apk_expansion/public_key=""
permissions/custom_permissions=PackedStringArray()
permissions/access_checkin_properties=false
permissions/access_coarse_location=false
permissions/access_fine_location=false
permissions/access_location_extra_commands=false
permissions/access_mock_location=false
permissions/access_network_state=true
permissions/access_surface_flinger=false
permissions/access_wifi_state=false
permissions/account_manager=false
permissions/add_voicemail=false
permissions/authenticate_accounts=false
permissions/battery_stats=false
permissions/bind_accessibility_service=false
permissions/bind_appwidget=false
permissions/bind_device_admin=false
permissions/bind_input_method=false
permissions/bind_nfc_service=false
permissions/bind_notification_listener_service=false
permissions/bind_print_service=false
permissions/bind_remoteviews=false
permissions/bind_text_service=false
permissions/bind_vpn_service=false
permissions/bind_wallpaper=false
permissions/bluetooth=false
permissions/bluetooth_admin=false
permissions/bluetooth_privileged=false
permissions/brick=false
permissions/broadcast_package_removed=false
permissions/broadcast_sms=false
permissions/broadcast_sticky=false
permissions/broadcast_wap_push=false
permissions/call_phone=false
permissions/call_privileged=false
permissions/camera=false
permissions/capture_audio_output=false
permissions/capture_secure_video_output=false
permissions/capture_video_output=false
permissions/change_component_enabled_state=false
permissions/change_configuration=false
permissions/change_network_state=false
permissions/change_wifi_multicast_state=false
permissions/change_wifi_state=false
permissions/clear_app_cache=false
permissions/clear_app_user_data=false
permissions/control_location_updates=false
permissions/delete_cache_files=false
permissions/delete_packages=false
permissions/device_power=false
permissions/diagnostic=false
permissions/disable_keyguard=false
permissions/dump=false
permissions/expand_status_bar=false
permissions/factory_test=false
permissions/flashlight=false
permissions/force_back=false
permissions/get_accounts=false
permissions/get_package_size=false
permissions/get_tasks=false
permissions/get_top_activity_info=false
permissions/global_search=false
permissions/hardware_test=false
permissions/inject_events=false
permissions/install_location_provider=false
permissions/install_packages=false
permissions/install_shortcut=false
permissions/internal_system_window=false
permissions/internet=true
permissions/kill_background_processes=false
permissions/location_hardware=false
permissions/manage_accounts=false
permissions/manage_app_tokens=false
permissions/manage_documents=false
permissions/manage_external_storage=false
permissions/master_clear=false
permissions/media_content_control=false
permissions/modify_audio_settings=false
permissions/modify_phone_state=false
permissions/mount_format_filesystems=false
permissions/mount_unmount_filesystems=false
permissions/nfc=false
permissions/persistent_activity=false
permissions/process_outgoing_calls=false
permissions/read_calendar=false
permissions/read_call_log=false
permissions/read_contacts=false
permissions/read_external_storage=true
permissions/read_frame_buffer=false
permissions/read_history_bookmarks=false
permissions/read_input_state=false
permissions/read_logs=false
permissions/read_phone_state=false
permissions/read_profile=false
permissions/read_sms=false
permissions/read_social_stream=false
permissions/read_sync_settings=false
permissions/read_sync_stats=false
permissions/read_user_dictionary=false
permissions/reboot=false
permissions/receive_boot_completed=false
permissions/receive_mms=false
permissions/receive_sms=false
permissions/receive_wap_push=false
permissions/record_audio=false
permissions/reorder_tasks=false
permissions/restart_packages=false
permissions/send_respond_via_message=false
permissions/send_sms=false
permissions/set_activity_watcher=false
permissions/set_alarm=false
permissions/set_always_finish=false
permissions/set_animation_scale=false
permissions/set_debug_app=false
permissions/set_orientation=false
permissions/set_pointer_speed=false
permissions/set_preferred_applications=false
permissions/set_process_limit=false
permissions/set_time=false
permissions/set_time_zone=false
permissions/set_wallpaper=false
permissions/set_wallpaper_hints=false
permissions/signal_persistent_processes=false
permissions/status_bar=false
permissions/subscribed_feeds_read=false
permissions/subscribed_feeds_write=false
permissions/system_alert_window=false
permissions/transmit_ir=false
permissions/uninstall_shortcut=false
permissions/update_device_stats=false
permissions/use_credentials=false
permissions/use_sip=false
permissions/vibrate=false
permissions/wake_lock=false
permissions/write_apn_settings=false
permissions/write_calendar=false
permissions/write_call_log=false
permissions/write_contacts=false
permissions/write_external_storage=true
permissions/write_gservices=false
permissions/write_history_bookmarks=false
permissions/write_profile=false
permissions/write_secure_settings=false
permissions/write_settings=false
permissions/write_sms=false
permissions/write_social_stream=false
permissions/write_sync_settings=false
permissions/write_user_dictionary=false

View File

@@ -1 +0,0 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><g transform="translate(32 32)"><path d="m-16-32c-8.86 0-16 7.13-16 15.99v95.98c0 8.86 7.13 15.99 16 15.99h96c8.86 0 16-7.13 16-15.99v-95.98c0-8.85-7.14-15.99-16-15.99z" fill="#363d52"/><path d="m-16-32c-8.86 0-16 7.13-16 15.99v95.98c0 8.86 7.13 15.99 16 15.99h96c8.86 0 16-7.13 16-15.99v-95.98c0-8.85-7.14-15.99-16-15.99zm0 4h96c6.64 0 12 5.35 12 11.99v95.98c0 6.64-5.35 11.99-12 11.99h-96c-6.64 0-12-5.35-12-11.99v-95.98c0-6.64 5.36-11.99 12-11.99z" fill-opacity=".4"/></g><g stroke-width="9.92746" transform="matrix(.10073078 0 0 .10073078 12.425923 2.256365)"><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 919.24059 771.67186)"/><path d="m0 0v-47.514-6.035-5.492c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325c5.09692 6.4164715 9.92323 13.494208 13.621 19.449-5.651 9.62-12.575 18.217-19.976 26.182-6.864-3.455-13.531-7.369-19.828-11.534-3.151 3.132-6.7 5.694-10.186 8.372-3.425 2.751-7.285 4.768-10.946 7.118 1.09 8.117 1.629 16.108 1.846 24.448-9.446 4.754-19.519 7.906-29.708 10.17-4.068-6.837-7.788-14.241-11.028-21.479-3.842.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.4426579-6.973692 9.2079702-13.9828876 13.621-19.449z" fill="#478cbf" transform="matrix(4.162611 0 0 -4.162611 104.69892 525.90697)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.066.067c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.162611 0 0 -4.162611 784.07144 817.24284)"/><path d="m0 0c0-12.052-9.765-21.815-21.813-21.815-12.042 0-21.81 9.763-21.81 21.815 0 12.044 9.768 21.802 21.81 21.802 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 389.21484 625.67104)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.162611 0 0 -4.162611 367.36686 631.05679)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 511.99336 724.73954)"/><path d="m0 0c0-12.052 9.765-21.815 21.815-21.815 12.041 0 21.808 9.763 21.808 21.815 0 12.044-9.767 21.802-21.808 21.802-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 634.78706 625.67104)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.162611 0 0 -4.162611 656.64056 631.05679)"/></g></svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,28 +1,28 @@
[gd_scene load_steps=6 format=3 uid="uid://8flqeh3gn68"]
[ext_resource type="Script" path="res://Renderer.gd" id="1_0maq1"]
[ext_resource type="Script" path="res://Main.gd" id="1_6qp7h"]
[ext_resource type="Texture2D" uid="uid://skthvfx7pq6m" path="res://_e2199ab5-ff42-4ddf-8540-1c16e2d7889f.jpeg" id="1_la77t"]
[ext_resource type="Script" path="res://JobServer.gd" id="3_mg2dt"]
[ext_resource type="Script" path="res://RemoteLoader.gd" id="4_k4afm"]
[ext_resource type="Script" path="res://scripts/Main.gd" id="1_wxvbd"]
[ext_resource type="Script" path="res://scripts/JobServer.gd" id="2_vpsid"]
[ext_resource type="Script" path="res://scripts/RemoteLoader.gd" id="3_18f1s"]
[ext_resource type="Texture2D" uid="uid://cxa8l2nu0ycg3" path="res://assets/icon.png" id="4_vknm6"]
[ext_resource type="Script" path="res://scripts/Renderer.gd" id="5_ps8c1"]
[node name="Main" type="Node2D"]
script = ExtResource("1_6qp7h")
script = ExtResource("1_wxvbd")
[node name="JobServer" type="HTTPRequest" parent="."]
script = ExtResource("3_mg2dt")
script = ExtResource("2_vpsid")
[node name="Remote" type="HTTPRequest" parent="."]
process_mode = 3
script = ExtResource("4_k4afm")
script = ExtResource("3_18f1s")
[node name="Placeholder" type="Sprite2D" parent="."]
visible = false
position = Vector2(580.25, 314.25)
scale = Vector2(0.532715, 0.532715)
texture = ExtResource("1_la77t")
texture = ExtResource("4_vknm6")
[node name="Renderer" type="Node2D" parent="."]
script = ExtResource("1_0maq1")
script = ExtResource("5_ps8c1")
[node name="RenderContainer" type="Node" parent="."]

View File

@@ -13,10 +13,11 @@ config_version=5
config/name="toho-reno"
run/main_scene="res://node_2d.tscn"
config/features=PackedStringArray("4.0", "GL Compatibility")
boot_splash/show_image=false
config/icon="res://icon.svg"
boot_splash/image="res://assets/icon.png"
config/icon="res://assets/icon.png"
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"
textures/vram_compression/import_etc2_astc=true

100
scripts/JobServer.gd Normal file
View File

@@ -0,0 +1,100 @@
extends HTTPRequest
var socket = WebSocketPeer.new()
var client_id
var connected = false
func InitWebsocket():
print("Connecting websocket ")
socket.max_queued_packets = 32768
socket.outbound_buffer_size = 5000000
socket.connect_to_url($"/root/Main".websocket_url, TLSOptions.client_unsafe())
var timeout = 5
while socket.get_ready_state() != WebSocketPeer.STATE_OPEN:
socket.poll()
await get_tree().create_timer(.25).timeout
timeout -= 0.25
if timeout <= 0:
timeout = 5
socket.connect_to_url($"/root/Main".websocket_url, TLSOptions.client_unsafe())
var init_message = {
"register": {
"version": 1,
"auth_key": $"/root/Main".auth_key,
"hostname": $"/root/Main".hostname
}
}
socket.send_text(str(init_message))
connected = true
print("Connected")
while connected:
await PollWebsocket()
RenderingServer.force_draw()
DisplayServer.process_events()
await get_tree().create_timer(0.1).timeout
func PollWebsocket():
var main = $"/root/Main"
socket.poll()
var state = socket.get_ready_state()
if state == WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
var packet = socket.get_packet()
var json = JSON.parse_string(packet.get_string_from_utf8())
print("Packet: ", packet.slice(0,5), "...")
if "welcome" in json:
print("Registered as client %s" % json["welcome"]["clientId"])
client_id = json["welcome"]["clientId"]
if "job" in json:
var job = json["job"]
print("Recevied Job ", job["jobId"])
main.rendering = true
var result_path = await $"../Renderer".RenderJob(job)
var result_value = ""
var result_type = "URL" if $"/root/Main".serve_mode == "local" else "B64:PNG"
if $"/root/Main".serve_mode == "local":
result_value = result_path
if $"/root/Main".serve_mode == "remote":
print("trying to open " + result_path)
var resut_file = FileAccess.open(result_path,FileAccess.READ)
result_value = "{path}:{data}".format({
"path": result_path.get_file(),
"data": Marshalls.raw_to_base64(resut_file.get_buffer(resut_file.get_length()))
})
var debugFile = FileAccess.open("user://debug.log", FileAccess.WRITE)
debugFile.store_string(result_value)
debugFile.flush()
debugFile.close()
var response = {
"result": {
"type": result_type,
"jobId": job["jobId"],
"value": result_value
}
}
print("[%s] Sending result via wss..." % str(response).length())
var time_start = Time.get_unix_time_from_system()
socket.send_text(str(response))
var time_elapsed = Time.get_unix_time_from_system() - time_start
print("Sent result in %s \n" % time_elapsed, result_path)
main.rendering = false
elif state == WebSocketPeer.STATE_CLOSING:
socket.poll()
elif state == WebSocketPeer.STATE_CLOSED:
print(socket.get_packet())
var code = socket.get_close_code()
var reason = socket.get_close_reason()
print("WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != -1])
print("Attempting reconnect in 5")
set_process(false) # Stop processing.
connected = false
await get_tree().create_timer(5).timeout
InitWebsocket()
func _process(_delta):
pass

View File

@@ -5,6 +5,10 @@ var config = ConfigFile.new()
var websocket_url
var public_path
var output_dir
var serve_mode
var cache_dir
var auth_key
var hostname
var rendering = false
signal finished_rendering
@@ -14,10 +18,20 @@ func _ready():
websocket_url = config.get_value("core", "websocket_url")
public_path = config.get_value("core", "public_path")
output_dir = config.get_value("core", "output_dir")
serve_mode = config.get_value("core", "serve_mode")
cache_dir = config.get_value("core", "cache_dir")
auth_key = config.get_value("core", "auth_key")
hostname = config.get_value("core", "hostname")
if OS.has_environment("USERNAME"):
hostname = "%s/%s" % [OS.get_environment("USERNAME"), hostname]
else:
hostname = "%s/%s" % [OS.get_name(), hostname]
print("Starting render node")
var directory = DirAccess.open(".")
directory.make_dir(output_dir)
DirAccess.make_dir_absolute(output_dir)
DirAccess.make_dir_absolute(cache_dir)
$JobServer.InitWebsocket()
func FinishedRendering():

42
scripts/RemoteLoader.gd Normal file
View File

@@ -0,0 +1,42 @@
extends HTTPRequest
func GetRemoteImage(url):
var image = Image.new()
print("Fetching remote image %s" % url)
var urlHash = str(url.hash())
var outFile = "{dir}/{hash}-{fileName}.png".format({
'dir': $"/root/Main".cache_dir,
'hash': urlHash,
'fileName': url.get_file().rsplit(".", true, 1)[0]
})
if FileAccess.file_exists(outFile):
image.load(outFile)
print("Loaded image from cache. " + outFile)
return image
timeout = 1000
request(url)
while get_http_client_status() != HTTPClient.STATUS_CONNECTED:
await get_tree().create_timer(0.001).timeout
$"/root/Main/JobServer".socket.poll()
var res = await request_completed
var magicBytes = res[3].slice(0,8)
print(magicBytes)
var fileType = url.get_extension()
var error = null
if fileType == "png" or magicBytes == PackedByteArray([137, 80, 78, 71, 13, 10, 26, 10]):
print("Detected PNG File")
error = image.load_png_from_buffer(res[3])
if ["jpg", "jpeg"].has(fileType) or magicBytes == PackedByteArray([255, 216, 255, 224, 0, 16, 74, 70]):
print("Detected JPG File")
error = image.load_jpg_from_buffer(res[3])
if error != OK:
print("Error fetching image ", str(error))
var fallback = load("res://assets/fallback_card.png")
image = fallback.get_image()
else:
image.save_png(outFile)
print("Saved new image to cache. " + outFile)
return image

View File

@@ -45,8 +45,12 @@ func RenderJob(job):
# Get rendered image
var img = get_viewport().get_texture().get_image()
var outFile = "%s_%s.png" % [job["type"],job["jobId"]]
img.save_png("%s/%s" % [$"/root/Main".output_dir, outFile])
var outFile = "{path}/{type}_{hash}.png".format({
"path":$"/root/Main".output_dir,
"type":job["type"],
"hash": str(job["elements"]).hash()
})
img.save_png(outFile)
return outFile
@@ -76,18 +80,24 @@ func RenderImage(def, zIndex):
var imageNode = TextureRect.new()
var image = Image.new()
image = await $"../Remote".GetRemoteImage(def["asset"])
var pos = Vector2(float(def["x"]), float(def["y"]))
var texture = ImageTexture.new()
texture = ImageTexture.create_from_image(image)
texture.set_size_override(Vector2(def["width"], def["height"]))
imageNode.texture = texture
imageNode.name = def["asset"].right(15)
imageNode.set_position(pos)
imageNode.z_index = zIndex
$"/root/Main/RenderContainer".add_child(imageNode)
print("Image added")
print("Image added at %s" % pos)
func RenderLabel(def, zIndex):
var textNode = Label.new()
textNode.text = def["text"]
var labelText = def["text"]
labelText = labelText.replace('%nodeid%', "%s: %s" % [$"/root/Main".hostname , $"/root/Main/JobServer".client_id])
labelText = labelText.replace('%servemode%', $"/root/Main".serve_mode)
labelText = labelText.replace('%timestamp%', Time.get_datetime_string_from_system())
textNode.text = labelText;
var pos = Vector2(float(def["x"]), float(def["y"]))
print("Rendering label '%s' at %s" % [def["text"], pos])
@@ -99,7 +109,7 @@ func RenderLabel(def, zIndex):
textNode.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
textNode.set_position(pos)
textNode.set_size(Vector2(float(def["width"]), float(def["height"])))
textNode.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
textNode.vertical_alignment = VERTICAL_ALIGNMENT_TOP
if "horizontalAlignment" in def:
var alignments = { "left": HORIZONTAL_ALIGNMENT_LEFT, "right": HORIZONTAL_ALIGNMENT_RIGHT, "center": HORIZONTAL_ALIGNMENT_CENTER, "fill": HORIZONTAL_ALIGNMENT_FILL }
textNode.horizontal_alignment = alignments[def["horizontalAlignment"]]