Start adding async loading
This commit is contained in:
parent
209bafa5f1
commit
1c328e3e2e
5 changed files with 159 additions and 5 deletions
147
Classes/ResourceQueue.gd
Normal file
147
Classes/ResourceQueue.gd
Normal file
|
@ -0,0 +1,147 @@
|
|||
class_name ResourceQueue
|
||||
|
||||
var thread
|
||||
var mutex
|
||||
var sem
|
||||
|
||||
var time_max = 100 # Milliseconds.
|
||||
|
||||
var queue = []
|
||||
var pending = {}
|
||||
|
||||
func _lock(_caller):
|
||||
mutex.lock()
|
||||
|
||||
|
||||
func _unlock(_caller):
|
||||
mutex.unlock()
|
||||
|
||||
|
||||
func _post(_caller):
|
||||
sem.post()
|
||||
|
||||
|
||||
func _wait(_caller):
|
||||
sem.wait()
|
||||
|
||||
|
||||
func queue_resource(path, p_in_front = false):
|
||||
_lock("queue_resource")
|
||||
if path in pending:
|
||||
_unlock("queue_resource")
|
||||
return
|
||||
elif ResourceLoader.has_cached(path):
|
||||
var res = ResourceLoader.load(path)
|
||||
pending[path] = res
|
||||
_unlock("queue_resource")
|
||||
return
|
||||
else:
|
||||
var res = ResourceLoader.load_interactive(path)
|
||||
res.set_meta("path", path)
|
||||
if p_in_front:
|
||||
queue.insert(0, res)
|
||||
else:
|
||||
queue.push_back(res)
|
||||
pending[path] = res
|
||||
_post("queue_resource")
|
||||
_unlock("queue_resource")
|
||||
return
|
||||
|
||||
|
||||
func cancel_resource(path):
|
||||
_lock("cancel_resource")
|
||||
if path in pending:
|
||||
if pending[path] is ResourceInteractiveLoader:
|
||||
queue.erase(pending[path])
|
||||
pending.erase(path)
|
||||
_unlock("cancel_resource")
|
||||
|
||||
|
||||
func get_progress(path):
|
||||
_lock("get_progress")
|
||||
var ret = -1
|
||||
if path in pending:
|
||||
if pending[path] is ResourceInteractiveLoader:
|
||||
ret = float(pending[path].get_stage()) / float(pending[path].get_stage_count())
|
||||
else:
|
||||
ret = 1.0
|
||||
_unlock("get_progress")
|
||||
return ret
|
||||
|
||||
|
||||
func is_ready(path):
|
||||
var ret
|
||||
_lock("is_ready")
|
||||
if path in pending:
|
||||
ret = !(pending[path] is ResourceInteractiveLoader)
|
||||
else:
|
||||
ret = false
|
||||
_unlock("is_ready")
|
||||
return ret
|
||||
|
||||
|
||||
func _wait_for_resource(res, path):
|
||||
_unlock("wait_for_resource")
|
||||
while true:
|
||||
VisualServer.sync()
|
||||
OS.delay_usec(16000) # Wait approximately 1 frame.
|
||||
_lock("wait_for_resource")
|
||||
if queue.size() == 0 || queue[0] != res:
|
||||
return pending[path]
|
||||
_unlock("wait_for_resource")
|
||||
|
||||
|
||||
func get_resource(path):
|
||||
_lock("get_resource")
|
||||
if path in pending:
|
||||
if pending[path] is ResourceInteractiveLoader:
|
||||
var res = pending[path]
|
||||
if res != queue[0]:
|
||||
var pos = queue.find(res)
|
||||
queue.remove(pos)
|
||||
queue.insert(0, res)
|
||||
|
||||
res = _wait_for_resource(res, path)
|
||||
pending.erase(path)
|
||||
_unlock("return")
|
||||
return res
|
||||
else:
|
||||
var res = pending[path]
|
||||
pending.erase(path)
|
||||
_unlock("return")
|
||||
return res
|
||||
else:
|
||||
_unlock("return")
|
||||
return ResourceLoader.load(path)
|
||||
|
||||
|
||||
func thread_process():
|
||||
_wait("thread_process")
|
||||
_lock("process")
|
||||
|
||||
while queue.size() > 0:
|
||||
var res = queue[0]
|
||||
_unlock("process_poll")
|
||||
var ret = res.poll()
|
||||
_lock("process_check_queue")
|
||||
|
||||
if ret == ERR_FILE_EOF || ret != OK:
|
||||
var path = res.get_meta("path")
|
||||
if path in pending: # Else, it was already retrieved.
|
||||
pending[res.get_meta("path")] = res.get_resource()
|
||||
# Something might have been put at the front of the queue while
|
||||
# we polled, so use erase instead of remove.
|
||||
queue.erase(res)
|
||||
_unlock("process")
|
||||
|
||||
|
||||
func thread_func(_u):
|
||||
while true:
|
||||
thread_process()
|
||||
|
||||
|
||||
func start():
|
||||
mutex = Mutex.new()
|
||||
sem = Semaphore.new()
|
||||
thread = Thread.new()
|
||||
thread.start(self, "thread_func", 0)
|
|
@ -6,6 +6,9 @@ class_name GameMap
|
|||
var ship_direction = 0
|
||||
var ship_speed = 0
|
||||
|
||||
var current_ship_position = Vector2.ZERO
|
||||
var current_ship_target = Vector2.ZERO
|
||||
|
||||
var current_ship_direction = 0
|
||||
var current_ship_speed = 0
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extends Control
|
||||
|
||||
export var scale = 2 setget set_scale
|
||||
export var scale = 4 setget set_scale
|
||||
export var upThreshold = 1.0/Engine.iterations_per_second
|
||||
export var downThreshold = 1.0/30.0
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ enum Map { RUNTIME, ODYSSEY }
|
|||
|
||||
export(Map) var mapToLoad = Map.RUNTIME
|
||||
|
||||
const runtimeRes = preload("res://Scenes/Maps/runtime.tscn")
|
||||
const odysseyRes = preload("res://Scenes/Maps/odyssey.tscn")
|
||||
const playerRes = preload("res://Actors/Player/Player.tscn")
|
||||
|
||||
var map = null
|
||||
|
@ -16,9 +14,9 @@ var player = null
|
|||
func _ready():
|
||||
match mapToLoad:
|
||||
Map.RUNTIME:
|
||||
map = runtimeRes.instance()
|
||||
map = load("res://Scenes/Maps/runtime.tscn").instance()
|
||||
Map.ODYSSEY:
|
||||
map = odysseyRes.instance()
|
||||
map = load("res://Scenes/Maps/odyssey.tscn").instance()
|
||||
add_child(map)
|
||||
player = playerRes.instance()
|
||||
player.is_controlled = true
|
||||
|
|
|
@ -94,6 +94,11 @@ _global_script_classes=[ {
|
|||
"language": "GDScript",
|
||||
"path": "res://Actors/Systems/Electricity/ElectricProbe.gd"
|
||||
}, {
|
||||
"base": "Reference",
|
||||
"class": "ResourceQueue",
|
||||
"language": "GDScript",
|
||||
"path": "res://Classes/ResourceQueue.gd"
|
||||
}, {
|
||||
"base": "Node2D",
|
||||
"class": "SpawnpointPlayer",
|
||||
"language": "GDScript",
|
||||
|
@ -122,6 +127,7 @@ _global_script_class_icons={
|
|||
"PowerManager": "",
|
||||
"PowerNetwork": "",
|
||||
"ProbeElectric": "",
|
||||
"ResourceQueue": "",
|
||||
"SpawnpointPlayer": "",
|
||||
"UICommand": ""
|
||||
}
|
||||
|
|
Reference in a new issue