#14,#15,#29,#31: Added qr, added more settings, added keymap, changed about page.
Build / build (push) Successful in 1m10s
Build / build (push) Successful in 1m10s
This commit is contained in:
@@ -0,0 +1,415 @@
|
||||
@tool
|
||||
@icon("res://addons/kenyoni/qr_code/icon.svg")
|
||||
extends TextureRect
|
||||
class_name QRCodeRect
|
||||
|
||||
const QRCode := preload("res://addons/kenyoni/qr_code/qr_code.gd")
|
||||
const ShiftJIS := preload("res://addons/kenyoni/qr_code/shift_jis.gd")
|
||||
|
||||
var mode: QRCode.Mode:
|
||||
set = set_mode,
|
||||
get = get_mode
|
||||
var error_correction: QRCode.ErrorCorrection:
|
||||
set = set_error_correction,
|
||||
get = get_error_correction
|
||||
## Use Extended Channel Interpretation (ECI).
|
||||
var use_eci: bool:
|
||||
set = set_use_eci,
|
||||
get = get_use_eci
|
||||
## Extended Channel Interpretation (ECI) Value.
|
||||
var eci_value: int:
|
||||
set = set_eci_value,
|
||||
get = get_eci_value
|
||||
var data: Variant = "":
|
||||
set = set_data,
|
||||
get = get_data
|
||||
## Automatically update the QR Code when a property changes.
|
||||
var auto_update: bool = true:
|
||||
set = set_auto_update
|
||||
## Use automatically the smallest version possible.
|
||||
var auto_version: bool = true:
|
||||
set = set_auto_version,
|
||||
get = get_auto_version
|
||||
var version: int = 1:
|
||||
set = set_version,
|
||||
get = get_version
|
||||
## Use automatically the best mask pattern.
|
||||
var auto_mask_pattern: bool = true:
|
||||
set = set_auto_mask_pattern,
|
||||
get = get_auto_mask_pattern
|
||||
## Used mask pattern.
|
||||
var mask_pattern: int = 0:
|
||||
set = set_mask_pattern,
|
||||
get = get_mask_pattern
|
||||
var light_module_color: Color = Color.WHITE:
|
||||
set = set_light_module_color
|
||||
var dark_module_color: Color = Color.BLACK:
|
||||
set = set_dark_module_color
|
||||
## Automatically set the module pixel size based on the size.
|
||||
## Do not use expand mode KEEP_SIZE when using it.
|
||||
## Turn this off when the QR Code is resized often, as it impacts the performance quite heavily.
|
||||
var auto_module_size: bool = true:
|
||||
set = set_auto_module_size
|
||||
## Use that many pixel for one module.
|
||||
## If auto_module_size is set, this value might by only occasionally updated. In this case do not rely on it.
|
||||
var module_size: int = 1:
|
||||
set = set_module_size
|
||||
## Use that many modules for the quiet zone. A value of 4 is recommended.
|
||||
var quiet_zone_size: int = 4:
|
||||
set = set_quiet_zone_size
|
||||
|
||||
var _qr: QRCode = QRCode.new()
|
||||
var _update_fn: Callable = self.update
|
||||
var _cached_data: PackedByteArray = PackedByteArray()
|
||||
|
||||
func set_mode(new_mode: QRCode.Mode) -> void:
|
||||
self._qr.mode = new_mode
|
||||
self.notify_property_list_changed()
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_mode() -> QRCode.Mode:
|
||||
return self._qr.mode
|
||||
|
||||
func set_error_correction(new_error_correction: QRCode.ErrorCorrection) -> void:
|
||||
self._qr.error_correction = new_error_correction
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_error_correction() -> QRCode.ErrorCorrection:
|
||||
return self._qr.error_correction
|
||||
|
||||
func set_use_eci(new_use_eci: bool) -> void:
|
||||
self._qr.use_eci = new_use_eci
|
||||
self.notify_property_list_changed()
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_use_eci() -> bool:
|
||||
return self._qr.use_eci
|
||||
|
||||
func set_eci_value(new_eci_value: int) -> void:
|
||||
if self._qr.eci_value == new_eci_value:
|
||||
return
|
||||
self._qr.eci_value = new_eci_value
|
||||
self.notify_property_list_changed()
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_eci_value() -> int:
|
||||
return self._qr.eci_value
|
||||
|
||||
func set_data(new_data: Variant) -> void:
|
||||
match self._qr.mode:
|
||||
QRCode.Mode.NUMERIC:
|
||||
self._qr.put_numeric(new_data)
|
||||
QRCode.Mode.ALPHANUMERIC:
|
||||
self._qr.put_alphanumeric(new_data)
|
||||
QRCode.Mode.BYTE:
|
||||
if typeof(new_data) == TYPE_PACKED_BYTE_ARRAY || ! self.use_eci:
|
||||
self._qr.put_byte(new_data)
|
||||
return
|
||||
match self.eci_value:
|
||||
QRCode.ECI.ISO_8859_1:
|
||||
self._qr.put_byte(new_data.to_ascii_buffer())
|
||||
QRCode.ECI.SHIFT_JIS:
|
||||
self._qr.put_byte(ShiftJIS.to_shift_jis_2004_buffer(new_data))
|
||||
QRCode.ECI.UTF_8:
|
||||
self._qr.put_byte(new_data.to_utf8_buffer())
|
||||
QRCode.ECI.UTF_16:
|
||||
self._qr.put_byte(new_data.to_utf16_buffer())
|
||||
QRCode.ECI.US_ASCII:
|
||||
self._qr.put_byte(new_data.to_ascii_buffer())
|
||||
_:
|
||||
self._qr.put_byte(new_data)
|
||||
QRCode.Mode.KANJI:
|
||||
self._qr.put_kanji(new_data)
|
||||
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_data() -> Variant:
|
||||
var input_data: Variant = self._qr.get_input_data()
|
||||
if self.mode == QRCode.Mode.BYTE && self.use_eci:
|
||||
match self.eci_value:
|
||||
QRCode.ECI.ISO_8859_1:
|
||||
return input_data.get_string_from_ascii()
|
||||
QRCode.ECI.SHIFT_JIS:
|
||||
return ShiftJIS.get_string_from_shift_jis_2004(input_data)
|
||||
QRCode.ECI.UTF_8:
|
||||
return input_data.get_string_from_utf8()
|
||||
QRCode.ECI.UTF_16:
|
||||
return input_data.get_string_from_utf16()
|
||||
QRCode.ECI.US_ASCII:
|
||||
return input_data.get_string_from_ascii()
|
||||
|
||||
return self._qr.get_input_data()
|
||||
|
||||
func set_auto_update(new_auto_update: bool) -> void:
|
||||
if auto_update == new_auto_update:
|
||||
return
|
||||
auto_update = new_auto_update
|
||||
self.notify_property_list_changed()
|
||||
if auto_update:
|
||||
self.update()
|
||||
|
||||
func set_auto_version(new_auto_version: bool) -> void:
|
||||
if self._qr.auto_version == new_auto_version:
|
||||
return
|
||||
self._qr.auto_version = new_auto_version
|
||||
self.notify_property_list_changed()
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_auto_version() -> bool:
|
||||
return self._qr.auto_version
|
||||
|
||||
func set_version(new_version: int) -> void:
|
||||
if self.auto_version || self._qr.version == new_version:
|
||||
return
|
||||
self._qr.version = new_version
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_version() -> int:
|
||||
return self._qr.version
|
||||
|
||||
func set_auto_mask_pattern(new_auto_mask_pattern: bool) -> void:
|
||||
if self._qr.auto_mask_pattern == new_auto_mask_pattern:
|
||||
return
|
||||
self._qr.auto_mask_pattern = new_auto_mask_pattern
|
||||
self.notify_property_list_changed()
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_auto_mask_pattern() -> bool:
|
||||
return self._qr.auto_mask_pattern
|
||||
|
||||
func set_mask_pattern(new_mask_pattern: int) -> void:
|
||||
if self.auto_mask_pattern || self._qr.mask_pattern == new_mask_pattern:
|
||||
return
|
||||
self._qr.mask_pattern = new_mask_pattern
|
||||
if self.auto_update:
|
||||
self.update()
|
||||
|
||||
func get_mask_pattern() -> int:
|
||||
return self._qr.mask_pattern
|
||||
|
||||
func set_light_module_color(new_light_module_color: Color) -> void:
|
||||
if light_module_color == new_light_module_color:
|
||||
return
|
||||
light_module_color = new_light_module_color
|
||||
if self.auto_update:
|
||||
self._update_texture()
|
||||
|
||||
func set_dark_module_color(new_dark_module_color: Color) -> void:
|
||||
if dark_module_color == new_dark_module_color:
|
||||
return
|
||||
dark_module_color = new_dark_module_color
|
||||
if self.auto_update:
|
||||
self._update_texture()
|
||||
|
||||
func set_auto_module_size(new_auto_module_size: bool) -> void:
|
||||
if auto_module_size == new_auto_module_size:
|
||||
return
|
||||
auto_module_size = new_auto_module_size
|
||||
self.notify_property_list_changed()
|
||||
self.update_configuration_warnings()
|
||||
if self.auto_update:
|
||||
self._update_texture()
|
||||
|
||||
func set_module_size(new_module_size: int) -> void:
|
||||
if module_size == new_module_size:
|
||||
return
|
||||
module_size = new_module_size
|
||||
# if not auto it was set directly
|
||||
if ! self.auto_module_size && self.auto_update:
|
||||
self._update_texture()
|
||||
|
||||
func set_quiet_zone_size(new_quiet_zone_size: int) -> void:
|
||||
if quiet_zone_size == new_quiet_zone_size:
|
||||
return
|
||||
quiet_zone_size = maxi(0, new_quiet_zone_size)
|
||||
if self.auto_module_size && self.auto_update:
|
||||
self._update_texture()
|
||||
elif self.auto_module_size:
|
||||
self._update_module_size()
|
||||
|
||||
func _ready() -> void:
|
||||
if self.texture != null && self.auto_update:
|
||||
self.update()
|
||||
|
||||
func update() -> void:
|
||||
self._cached_data = self._qr.encode()
|
||||
self._update_texture()
|
||||
|
||||
func _set(property: StringName, value: Variant) -> bool:
|
||||
if property == "expand_mode":
|
||||
self.update_configuration_warnings()
|
||||
|
||||
return false
|
||||
|
||||
func _get_property_list() -> Array[Dictionary]:
|
||||
var data_prop: Dictionary = {
|
||||
"name": "data",
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
}
|
||||
match self.mode:
|
||||
QRCode.Mode.NUMERIC:
|
||||
data_prop["type"] = TYPE_STRING
|
||||
QRCode.Mode.ALPHANUMERIC, QRCode.Mode.KANJI:
|
||||
data_prop["type"] = TYPE_STRING
|
||||
data_prop["hint"] = PROPERTY_HINT_MULTILINE_TEXT
|
||||
QRCode.Mode.BYTE:
|
||||
# these encoding is natively supported
|
||||
if self.use_eci && self.eci_value in [QRCode.ECI.ISO_8859_1, QRCode.ECI.SHIFT_JIS, QRCode.ECI.UTF_8, QRCode.ECI.UTF_16, QRCode.ECI.US_ASCII]:
|
||||
data_prop["type"] = TYPE_STRING
|
||||
data_prop["hint"] = PROPERTY_HINT_MULTILINE_TEXT
|
||||
else:
|
||||
data_prop["type"] = TYPE_PACKED_BYTE_ARRAY
|
||||
|
||||
return [
|
||||
{
|
||||
"name": "_update_fn",
|
||||
"type": TYPE_CALLABLE,
|
||||
"usage": PROPERTY_USAGE_NONE if self.auto_update else PROPERTY_USAGE_EDITOR,
|
||||
"hint": PROPERTY_HINT_TOOL_BUTTON,
|
||||
"hint_string": "Update"
|
||||
},
|
||||
{
|
||||
"name": "auto_update",
|
||||
"type": TYPE_BOOL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "mode",
|
||||
"type": TYPE_INT,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Numeric:1,Alphanumeric:2,Byte:4,Kanji:8"
|
||||
},
|
||||
{
|
||||
"name": "error_correction",
|
||||
"type": TYPE_INT,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Low:1,Medium:0,Quartile:3,High:2"
|
||||
},
|
||||
{
|
||||
"name": "use_eci",
|
||||
"type": TYPE_BOOL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "eci_value",
|
||||
"type": TYPE_INT,
|
||||
"usage": (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE) if self.use_eci else (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY),
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Code Page 437:2,ISO 8859-1:3,ISO 8859-2:4,ISO 8859-3:5,ISO 8859-4:6,ISO 8859-5:7,ISO 8859-6:8,ISO 8859-7:9,ISO 8859-8:10,ISO 8859-9:11,ISO 8859-10:12,ISO 8859-11:13,ISO 8859-12:14,ISO 8859-13:15,ISO 8859-14:16,ISO 8859-15:17,ISO 8859-16:18,Shift JIS:20,Windows 1250:21,Windows 1251:22,Windows 1252:23,Windows 1256:24,UTF-16:25,UTF-8:26,US ASCII:27,BIG 5:28,GB 18030:29,EUC KR:30"
|
||||
},
|
||||
data_prop,
|
||||
{
|
||||
"name": "auto_version",
|
||||
"type": TYPE_BOOL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"type": TYPE_INT,
|
||||
"usage": (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY) if self.auto_version else (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE),
|
||||
"hint": PROPERTY_HINT_RANGE,
|
||||
"hint_string": "1,40"
|
||||
},
|
||||
{
|
||||
"name": "auto_mask_pattern",
|
||||
"type": TYPE_BOOL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "mask_pattern",
|
||||
"type": TYPE_INT,
|
||||
"usage": (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY) if self.auto_mask_pattern else (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE),
|
||||
"hint": PROPERTY_HINT_RANGE,
|
||||
"hint_string": "0,7"
|
||||
},
|
||||
{
|
||||
"name": "Appearance",
|
||||
"type": TYPE_NIL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_GROUP,
|
||||
},
|
||||
{
|
||||
"name": "light_module_color",
|
||||
"type": TYPE_COLOR,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "dark_module_color",
|
||||
"type": TYPE_COLOR,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "auto_module_size",
|
||||
"type": TYPE_BOOL,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
},
|
||||
{
|
||||
"name": "module_size",
|
||||
"type": TYPE_INT,
|
||||
"usage": (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY) if self.auto_module_size else (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE),
|
||||
"hint": PROPERTY_HINT_RANGE,
|
||||
"hint_string": "1,1,or_greater"
|
||||
},
|
||||
{
|
||||
"name": "quiet_zone_size",
|
||||
"type": TYPE_INT,
|
||||
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE,
|
||||
"hint_string": "0,1,or_greater",
|
||||
},
|
||||
]
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if property.name == "texture":
|
||||
property.usage &= ~(PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE)
|
||||
|
||||
func _property_can_revert(property: StringName) -> bool:
|
||||
return property in ["eci_value", "auto_version", "auto_mask_pattern", "light_module_color", "dark_module_color", "auto_module_size", "quiet_zone_size"]
|
||||
|
||||
func _property_get_revert(property: StringName) -> Variant:
|
||||
match property:
|
||||
"eci_value":
|
||||
return QRCode.ECI.ISO_8859_1
|
||||
"auto_version":
|
||||
return true
|
||||
"auto_mask_pattern":
|
||||
return true
|
||||
"light_module_color":
|
||||
return Color.WHITE
|
||||
"dark_module_color":
|
||||
return Color.BLACK
|
||||
"auto_module_size":
|
||||
return true
|
||||
"quiet_zone_size":
|
||||
return 4
|
||||
_:
|
||||
return null
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
if self.auto_module_size && self.expand_mode == EXPAND_KEEP_SIZE:
|
||||
return ["Do not use auto module px size AND keep size expand mode."]
|
||||
return []
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
match what:
|
||||
NOTIFICATION_RESIZED:
|
||||
if self.auto_module_size && self.auto_update:
|
||||
self._update_texture()
|
||||
elif self.auto_module_size:
|
||||
self._update_module_size()
|
||||
|
||||
func _update_module_size() -> void:
|
||||
self.module_size = mini(self.size.x, self.size.y) / (self._qr.get_dimension() + 2 * self.quiet_zone_size)
|
||||
|
||||
func _update_texture() -> void:
|
||||
if self.auto_module_size:
|
||||
self._update_module_size()
|
||||
self.texture = ImageTexture.create_from_image(QRCode.generate_image(self._cached_data, self.module_size, self.light_module_color, self.dark_module_color, self.quiet_zone_size))
|
||||
Reference in New Issue
Block a user