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_direction = 0
|
||||||
var ship_speed = 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_direction = 0
|
||||||
var current_ship_speed = 0
|
var current_ship_speed = 0
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
extends Control
|
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 upThreshold = 1.0/Engine.iterations_per_second
|
||||||
export var downThreshold = 1.0/30.0
|
export var downThreshold = 1.0/30.0
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ enum Map { RUNTIME, ODYSSEY }
|
||||||
|
|
||||||
export(Map) var mapToLoad = Map.RUNTIME
|
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")
|
const playerRes = preload("res://Actors/Player/Player.tscn")
|
||||||
|
|
||||||
var map = null
|
var map = null
|
||||||
|
@ -16,9 +14,9 @@ var player = null
|
||||||
func _ready():
|
func _ready():
|
||||||
match mapToLoad:
|
match mapToLoad:
|
||||||
Map.RUNTIME:
|
Map.RUNTIME:
|
||||||
map = runtimeRes.instance()
|
map = load("res://Scenes/Maps/runtime.tscn").instance()
|
||||||
Map.ODYSSEY:
|
Map.ODYSSEY:
|
||||||
map = odysseyRes.instance()
|
map = load("res://Scenes/Maps/odyssey.tscn").instance()
|
||||||
add_child(map)
|
add_child(map)
|
||||||
player = playerRes.instance()
|
player = playerRes.instance()
|
||||||
player.is_controlled = true
|
player.is_controlled = true
|
||||||
|
|
|
@ -94,6 +94,11 @@ _global_script_classes=[ {
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://Actors/Systems/Electricity/ElectricProbe.gd"
|
"path": "res://Actors/Systems/Electricity/ElectricProbe.gd"
|
||||||
}, {
|
}, {
|
||||||
|
"base": "Reference",
|
||||||
|
"class": "ResourceQueue",
|
||||||
|
"language": "GDScript",
|
||||||
|
"path": "res://Classes/ResourceQueue.gd"
|
||||||
|
}, {
|
||||||
"base": "Node2D",
|
"base": "Node2D",
|
||||||
"class": "SpawnpointPlayer",
|
"class": "SpawnpointPlayer",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
|
@ -122,6 +127,7 @@ _global_script_class_icons={
|
||||||
"PowerManager": "",
|
"PowerManager": "",
|
||||||
"PowerNetwork": "",
|
"PowerNetwork": "",
|
||||||
"ProbeElectric": "",
|
"ProbeElectric": "",
|
||||||
|
"ResourceQueue": "",
|
||||||
"SpawnpointPlayer": "",
|
"SpawnpointPlayer": "",
|
||||||
"UICommand": ""
|
"UICommand": ""
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue