From 2758e507595e6a34da0ff75b866f2ccaea4f1a7d Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Mon, 31 Jul 2023 15:18:02 +0930 Subject: [PATCH] Partial menu theme --- box.tscn | 15 +++++ main_menu.tscn | 55 +++++++++++++++ project.godot | 8 ++- shaders/box_shadermat.tres | 101 ++++++++++++++++++++++++++++ Node2D.gd => test_scene.gd | 7 ++ Node2D.tscn => test_scene.tscn | 16 ++--- theme/border.png | Bin 0 -> 215 bytes theme/border.png.import | 13 ++++ theme/border_imagetexture.tres | 16 +++++ theme/border_stylebox.tres | 11 +++ theme/menu_theme.tres | 37 ++++++++++ theme/slider7px.png | Bin 0 -> 195 bytes theme/slider7px.png.import | 35 ++++++++++ theme/slider7px_inner_stylebox.tres | 7 ++ theme/slider7px_stylebox.tres | 14 ++++ theme/slider8px.png | Bin 0 -> 202 bytes theme/slider8px.png.import | 35 ++++++++++ theme/slider8px_inner_stylebox.tres | 7 ++ theme/slider8px_stylebox.tres | 14 ++++ widgets/ColorMenu.gd | 38 +++++++++++ widgets/ColorMenu.tscn | 56 +++++++++++++++ 21 files changed, 475 insertions(+), 10 deletions(-) create mode 100644 box.tscn create mode 100644 main_menu.tscn create mode 100644 shaders/box_shadermat.tres rename Node2D.gd => test_scene.gd (56%) rename Node2D.tscn => test_scene.tscn (62%) create mode 100644 theme/border.png create mode 100644 theme/border.png.import create mode 100644 theme/border_imagetexture.tres create mode 100644 theme/border_stylebox.tres create mode 100644 theme/menu_theme.tres create mode 100644 theme/slider7px.png create mode 100644 theme/slider7px.png.import create mode 100644 theme/slider7px_inner_stylebox.tres create mode 100644 theme/slider7px_stylebox.tres create mode 100644 theme/slider8px.png create mode 100644 theme/slider8px.png.import create mode 100644 theme/slider8px_inner_stylebox.tres create mode 100644 theme/slider8px_stylebox.tres create mode 100644 widgets/ColorMenu.gd create mode 100644 widgets/ColorMenu.tscn diff --git a/box.tscn b/box.tscn new file mode 100644 index 0000000..51ca962 --- /dev/null +++ b/box.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://theme/border.png" type="Texture" id=1] +[ext_resource path="res://shaders/box_shadermat.tres" type="Material" id=2] + +[node name="box" type="NinePatchRect"] +material = ExtResource( 2 ) +margin_right = 8.0 +margin_bottom = 8.0 +rect_min_size = Vector2( 10, 10 ) +texture = ExtResource( 1 ) +patch_margin_left = 4 +patch_margin_top = 4 +patch_margin_right = 4 +patch_margin_bottom = 4 diff --git a/main_menu.tscn b/main_menu.tscn new file mode 100644 index 0000000..6f86c53 --- /dev/null +++ b/main_menu.tscn @@ -0,0 +1,55 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://box.tscn" type="PackedScene" id=1] +[ext_resource path="res://theme/menu_theme.tres" type="Theme" id=2] +[ext_resource path="res://widgets/ColorMenu.tscn" type="PackedScene" id=3] +[ext_resource path="res://theme/border_imagetexture.tres" type="Texture" id=4] + +[node name="main_menu" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_scale = Vector2( 2, 2 ) +theme = ExtResource( 2 ) + +[node name="MarginContainer" type="MarginContainer" parent="."] +margin_right = 70.0 +margin_bottom = 32.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 + +[node name="box2" parent="MarginContainer" instance=ExtResource( 1 )] +material = null +margin_right = 101.0 +margin_bottom = 37.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +texture = ExtResource( 4 ) + +[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer"] +margin_right = 101.0 +margin_bottom = 37.0 +custom_constants/margin_right = 4 +custom_constants/margin_top = 4 +custom_constants/margin_left = 4 +custom_constants/margin_bottom = 4 + +[node name="Label" type="Label" parent="MarginContainer/MarginContainer2"] +margin_left = 4.0 +margin_top = 4.0 +margin_right = 97.0 +margin_bottom = 33.0 +text = "Load Save File +From here" + +[node name="Button" type="Button" parent="."] +margin_left = 40.0 +margin_top = 40.0 +margin_right = 124.0 +margin_bottom = 61.0 +text = "Test Button" + +[node name="ColorMenu" parent="." instance=ExtResource( 3 )] +margin_left = 44.0 +margin_top = 64.0 +margin_right = 129.0 +margin_bottom = 128.0 diff --git a/project.godot b/project.godot index b82600f..7f0eb3b 100644 --- a/project.godot +++ b/project.godot @@ -15,7 +15,7 @@ _global_script_class_icons={ [application] config/name="FF" -run/main_scene="res://Node2D.tscn" +run/main_scene="res://test_scene.tscn" config/icon="res://icon.png" [autoload] @@ -38,8 +38,12 @@ gdscript/warnings/integer_division=false color=false +[gui] + +theme/use_hidpi=true + [rendering] quality/driver/driver_name="GLES2" -environment/default_clear_color=Color( 0, 0, 0.517647, 1 ) +environment/default_clear_color=Color( 0, 0, 0, 1 ) environment/default_environment="res://default_env.tres" diff --git a/shaders/box_shadermat.tres b/shaders/box_shadermat.tres new file mode 100644 index 0000000..15380a4 --- /dev/null +++ b/shaders/box_shadermat.tres @@ -0,0 +1,101 @@ +[gd_resource type="ShaderMaterial" load_steps=9 format=2] + +[sub_resource type="VisualShaderNodeVectorDecompose" id=7] + +[sub_resource type="VisualShaderNodeScalarOp" id=2] +output_port_for_preview = 0 +default_input_values = [ 0, 0.1, 1, 0.01 ] +operator = 9 + +[sub_resource type="VisualShaderNodeColorUniform" id=5] +uniform_name = "MenuBGColour" +default_value_enabled = true +default_value = Color( 0, 0, 0.517647, 1 ) + +[sub_resource type="VisualShaderNodeVectorScalarMix" id=6] +output_port_for_preview = 0 + +[sub_resource type="VisualShaderNodeInput" id=8] +input_name = "texture" + +[sub_resource type="VisualShaderNodeInput" id=9] +input_name = "uv" + +[sub_resource type="VisualShaderNodeTexture" id=10] +source = 5 + +[sub_resource type="VisualShader" id=3] +code = "shader_type canvas_item; +uniform vec4 MenuBGColour : hint_color = vec4(0.000000, 0.000000, 0.517647, 1.000000); + + + +void vertex() { +// Output:0 + +} + +void fragment() { +// Input:8 + vec3 n_out8p0 = vec3(UV, 0.0); + +// Input:7 + +// Texture:9 + vec3 n_out9p0; + float n_out9p1; + { + vec4 TEXTURE_tex_read = texture(TEXTURE, n_out8p0.xy); + n_out9p0 = TEXTURE_tex_read.rgb; + n_out9p1 = TEXTURE_tex_read.a; + } + +// ColorUniform:5 + vec3 n_out5p0 = MenuBGColour.rgb; + float n_out5p1 = MenuBGColour.a; + +// VectorDecompose:10 + float n_out10p0 = n_out9p0.x; + float n_out10p1 = n_out9p0.y; + float n_out10p2 = n_out9p0.z; + +// ScalarOp:3 + float n_in3p1 = 0.01000; + float n_out3p0 = step(n_out10p0, n_in3p1); + +// VectorScalarMix:6 + vec3 n_out6p0 = mix(n_out9p0, n_out5p0, n_out3p0); + +// Output:0 + COLOR.rgb = n_out6p0; + COLOR.a = n_out9p1; + +} + +void light() { +// Output:0 + +} +" +graph_offset = Vector2( -751, -138 ) +mode = 1 +flags/light_only = false +nodes/fragment/3/node = SubResource( 2 ) +nodes/fragment/3/position = Vector2( -80, -60 ) +nodes/fragment/5/node = SubResource( 5 ) +nodes/fragment/5/position = Vector2( -600, 240 ) +nodes/fragment/6/node = SubResource( 6 ) +nodes/fragment/6/position = Vector2( 120, 60 ) +nodes/fragment/7/node = SubResource( 8 ) +nodes/fragment/7/position = Vector2( -680, 120 ) +nodes/fragment/8/node = SubResource( 9 ) +nodes/fragment/8/position = Vector2( -680, 60 ) +nodes/fragment/9/node = SubResource( 10 ) +nodes/fragment/9/position = Vector2( -500, 60 ) +nodes/fragment/10/node = SubResource( 7 ) +nodes/fragment/10/position = Vector2( -380, -60 ) +nodes/fragment/connections = PoolIntArray( 5, 0, 6, 1, 3, 0, 6, 2, 6, 0, 0, 0, 7, 0, 9, 2, 8, 0, 9, 0, 9, 1, 0, 1, 9, 0, 6, 0, 9, 0, 10, 0, 10, 0, 3, 0 ) + +[resource] +shader = SubResource( 3 ) +shader_param/MenuBGColour = Color( 0, 0, 0.517647, 1 ) diff --git a/Node2D.gd b/test_scene.gd similarity index 56% rename from Node2D.gd rename to test_scene.gd index d47d135..9c3113d 100644 --- a/Node2D.gd +++ b/test_scene.gd @@ -12,3 +12,10 @@ func _ready(): save_slots.append(SaveLoader.get_save_slot(save_file, i)) save_slot_dicts.append(SaveLoader.get_struct(save_slots[i], 'Save_slot')) print('Loaded test save file') + save_file.close() + # error = save_file.open('downloaded_saves/psx_world1.gme', File.READ) + # if error == OK: + # var buffer := StreamPeerBuffer.new() + # save_file.seek(0x2FA0) + # buffer.data_array = save_file.get_buffer(0x600) + # save_slot_dicts.append(SaveLoader.get_struct(buffer, 'Save_slot')) diff --git a/Node2D.tscn b/test_scene.tscn similarity index 62% rename from Node2D.tscn rename to test_scene.tscn index 96e1ff8..f300a08 100644 --- a/Node2D.tscn +++ b/test_scene.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=6 format=2] [ext_resource path="res://palette_mat.tres" type="Material" id=1] -[ext_resource path="res://Node2D.gd" type="Script" id=2] -[ext_resource path="res://test/audio_system.tscn" type="PackedScene" id=3] -[ext_resource path="res://test/worldmap_system.tscn" type="PackedScene" id=4] -[ext_resource path="res://test/battle_sprites.tscn" type="PackedScene" id=5] +[ext_resource path="res://test/worldmap_system.tscn" type="PackedScene" id=2] +[ext_resource path="res://test_scene.gd" type="Script" id=3] +[ext_resource path="res://test/battle_sprites.tscn" type="PackedScene" id=4] +[ext_resource path="res://test/audio_system.tscn" type="PackedScene" id=5] [node name="Control" type="Control"] anchor_right = 1.0 @@ -14,11 +14,11 @@ anchor_bottom = 1.0 material = ExtResource( 1 ) position = Vector2( 16, 16 ) scale = Vector2( 2, 2 ) -script = ExtResource( 2 ) +script = ExtResource( 3 ) -[node name="audio_system" parent="." instance=ExtResource( 3 )] +[node name="audio_system" parent="." instance=ExtResource( 5 )] position = Vector2( 0, 400 ) -[node name="worldmap_system" parent="." instance=ExtResource( 4 )] +[node name="worldmap_system" parent="." instance=ExtResource( 2 )] -[node name="battle_sprites" parent="." instance=ExtResource( 5 )] +[node name="battle_sprites" parent="." instance=ExtResource( 4 )] diff --git a/theme/border.png b/theme/border.png new file mode 100644 index 0000000000000000000000000000000000000000..0f4548b1854225f782def17713fa45938d2053c9 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevDDT6R$#Zvn+pdfpR zr>`sfb9Q-lC5HP(UeAC+k|nMYCC>S|xv6<249-QVi6yBi3gww484B*6z5(HleBwYw zfu1goArhB+CpdB)Fc4r$cmB6_-yU1mOG{cRCZ)z4VcPJwV8Yu~jGn(*Cox<|&yZj|Y~5eBc_n{0o*wF58`vL>P*f^_yuw>gQu&X%Q~lo FCICthN1y-z literal 0 HcmV?d00001 diff --git a/theme/border.png.import b/theme/border.png.import new file mode 100644 index 0000000..817ba17 --- /dev/null +++ b/theme/border.png.import @@ -0,0 +1,13 @@ +[remap] + +importer="image" +type="Image" +path="res://.import/border.png-b5dfcc5f3c6971cc0b4cfe3e3b83fbb0.image" + +[deps] + +source_file="res://theme/border.png" +dest_files=[ "res://.import/border.png-b5dfcc5f3c6971cc0b4cfe3e3b83fbb0.image" ] + +[params] + diff --git a/theme/border_imagetexture.tres b/theme/border_imagetexture.tres new file mode 100644 index 0000000..9998176 --- /dev/null +++ b/theme/border_imagetexture.tres @@ -0,0 +1,16 @@ +[gd_resource type="ImageTexture" load_steps=2 format=2] + +[sub_resource type="Image" id=1] +data = { +"data": PoolByteArray( 31, 0, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 0, 128, 255, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 255, 128, 255, 128, 255, 255, 255, 255, 255, 128, 255, 128, 255, 128, 255, 128, 255, 255, 255, 255, 255, 128, 255, 128, 255, 255, 255, 128, 255, 128, 255, 0, 255, 0, 255, 128, 255, 128, 255, 255, 255, 128, 255, 128, 255, 255, 255, 128, 255, 0, 255, 0, 255, 0, 255, 0, 255, 128, 255, 255, 255, 128, 255, 128, 255, 255, 255, 128, 255, 0, 255, 0, 255, 0, 255, 0, 255, 128, 255, 255, 255, 128, 255, 128, 255, 255, 255, 128, 255, 128, 255, 0, 255, 0, 255, 128, 255, 128, 255, 255, 255, 128, 255, 128, 255, 255, 255, 255, 255, 128, 255, 128, 255, 128, 255, 128, 255, 255, 255, 255, 255, 128, 255, 128, 255, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 255, 128, 255, 128, 0, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 255, 128, 0 ), +"format": "LumAlpha8", +"height": 10, +"mipmaps": false, +"width": 10 +} + +[resource] +flags = 2 +flags = 2 +image = SubResource( 1 ) +size = Vector2( 10, 10 ) diff --git a/theme/border_stylebox.tres b/theme/border_stylebox.tres new file mode 100644 index 0000000..bcca497 --- /dev/null +++ b/theme/border_stylebox.tres @@ -0,0 +1,11 @@ +[gd_resource type="StyleBoxTexture" load_steps=2 format=2] + +[ext_resource path="res://theme/border_imagetexture.tres" type="Texture" id=1] + +[resource] +texture = ExtResource( 1 ) +region_rect = Rect2( 0, 0, 10, 10 ) +margin_left = 4.0 +margin_right = 4.0 +margin_top = 4.0 +margin_bottom = 4.0 diff --git a/theme/menu_theme.tres b/theme/menu_theme.tres new file mode 100644 index 0000000..a6cbbd9 --- /dev/null +++ b/theme/menu_theme.tres @@ -0,0 +1,37 @@ +[gd_resource type="Theme" load_steps=8 format=2] + +[ext_resource path="res://3rd_party/sysfont/dynamicfont.tres" type="DynamicFont" id=1] +[ext_resource path="res://theme/border_stylebox.tres" type="StyleBox" id=2] +[ext_resource path="res://theme/slider8px_inner_stylebox.tres" type="StyleBox" id=3] +[ext_resource path="res://theme/slider8px_stylebox.tres" type="StyleBox" id=4] + +[sub_resource type="ImageTexture" id=4] + +[sub_resource type="ImageTexture" id=2] + +[sub_resource type="ImageTexture" id=3] + +[resource] +default_font = ExtResource( 1 ) +Button/colors/font_color = Color( 1, 1, 1, 1 ) +Button/styles/normal = ExtResource( 2 ) +HSlider/icons/grabber = SubResource( 4 ) +HSlider/icons/grabber_disabled = SubResource( 2 ) +HSlider/icons/grabber_highlight = SubResource( 3 ) +HSlider/styles/grabber_area = ExtResource( 3 ) +HSlider/styles/grabber_area_highlight = ExtResource( 3 ) +HSlider/styles/slider = ExtResource( 4 ) +Label/colors/font_color = Color( 1, 1, 1, 1 ) +Label/colors/font_color_shadow = Color( 0, 0, 0, 0.501961 ) +Label/constants/line_spacing = 1 +Label/constants/shadow_as_outline = 0 +Label/constants/shadow_offset_x = 1 +Label/constants/shadow_offset_y = 1 +Panel/styles/panel = ExtResource( 2 ) +TabContainer/colors/font_color_bg = Color( 0.501961, 0.501961, 0.501961, 1 ) +TabContainer/colors/font_color_fg = Color( 1, 1, 1, 1 ) +TabContainer/styles/panel = ExtResource( 2 ) +TabContainer/styles/tab_bg = ExtResource( 2 ) +TabContainer/styles/tab_disabled = ExtResource( 2 ) +TabContainer/styles/tab_fg = ExtResource( 2 ) +Tree/styles/bg = ExtResource( 2 ) diff --git a/theme/slider7px.png b/theme/slider7px.png new file mode 100644 index 0000000000000000000000000000000000000000..629ba129f88ca8d5e077f4e281ef11a45808e0af GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^AT~P(3y_?>ROAJa;w&SJ$K)~su`O@$6&YXO!)SC0isii;a;E}*U!-d_A3+8d=`n23jQ1yKD l`sfb9Q+)Ara}EL-9Z%$r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj3H&C`DJ)+g4MzWuijr`KNPM0_fb*^$c+r1u6{1-oD!M<)H6OE literal 0 HcmV?d00001 diff --git a/theme/slider8px.png.import b/theme/slider8px.png.import new file mode 100644 index 0000000..2b4c479 --- /dev/null +++ b/theme/slider8px.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/slider8px.png-c0fbf5cf8d0d492a4e80c8338242c5ab.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://theme/slider8px.png" +dest_files=[ "res://.import/slider8px.png-c0fbf5cf8d0d492a4e80c8338242c5ab.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=1 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=0 +process/fix_alpha_border=false +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/theme/slider8px_inner_stylebox.tres b/theme/slider8px_inner_stylebox.tres new file mode 100644 index 0000000..6599ac7 --- /dev/null +++ b/theme/slider8px_inner_stylebox.tres @@ -0,0 +1,7 @@ +[gd_resource type="StyleBoxTexture" load_steps=2 format=2] + +[ext_resource path="res://theme/slider8px.png" type="Texture" id=1] + +[resource] +texture = ExtResource( 1 ) +region_rect = Rect2( 4, 0, 2, 8 ) diff --git a/theme/slider8px_stylebox.tres b/theme/slider8px_stylebox.tres new file mode 100644 index 0000000..b1ffc4e --- /dev/null +++ b/theme/slider8px_stylebox.tres @@ -0,0 +1,14 @@ +[gd_resource type="StyleBoxTexture" load_steps=2 format=2] + +[ext_resource path="res://theme/slider8px.png" type="Texture" id=1] + +[resource] +texture = ExtResource( 1 ) +region_rect = Rect2( 0, 0, 10, 8 ) +margin_left = 4.0 +margin_right = 4.0 +margin_top = 1.0 +margin_bottom = 1.0 +expand_margin_left = 4.0 +expand_margin_right = 4.0 +draw_center = false diff --git a/widgets/ColorMenu.gd b/widgets/ColorMenu.gd new file mode 100644 index 0000000..9e85adb --- /dev/null +++ b/widgets/ColorMenu.gd @@ -0,0 +1,38 @@ +extends Panel +var r := 0 +var g := 0 +var b := 16 + +var border_image: Image = preload('res://theme/border.png') +var border_texture := preload('res://theme/border_imagetexture.tres') +var border_stylebox := preload('res://theme/border_stylebox.tres') +const r1 := Rect2(4, 3, 2, 4) +const r2 := Rect2(3, 4, 4, 2) + +func update_menu_color() -> void: + var c := Color(r/31.0, g/31.0, b/31.0) + # print(c) + $label_nums.text = '\n%d\n%d\n%d' % [r, g, b] + border_image.fill_rect(r1, c) + border_image.fill_rect(r2, c) + border_texture.set_data(border_image) + # border_stylebox.texture = border_texture + # update() + +func _ready() -> void: + border_texture.create_from_image(border_image, 0) + $slider_r.value = r + $slider_g.value = g + $slider_b.value = b + +func _on_slider_r_value_changed(value: float) -> void: + r = value + update_menu_color() + +func _on_slider_g_value_changed(value: float) -> void: + g = value + update_menu_color() + +func _on_slider_b_value_changed(value: float) -> void: + b = value + update_menu_color() diff --git a/widgets/ColorMenu.tscn b/widgets/ColorMenu.tscn new file mode 100644 index 0000000..a1d85bf --- /dev/null +++ b/widgets/ColorMenu.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://theme/menu_theme.tres" type="Theme" id=1] +[ext_resource path="res://widgets/ColorMenu.gd" type="Script" id=2] + +[node name="Panel" type="Panel"] +margin_right = 85.0 +margin_bottom = 64.0 +theme = ExtResource( 1 ) +script = ExtResource( 2 ) + +[node name="Label" type="Label" parent="."] +margin_left = 4.0 +margin_top = 3.0 +margin_right = 79.0 +margin_bottom = 62.0 +text = "Menu Color +R +G +B" + +[node name="label_nums" type="Label" parent="."] +margin_left = 4.0 +margin_top = 3.0 +margin_right = 79.0 +margin_bottom = 62.0 +text = " +0 +0 +0" +align = 2 + +[node name="slider_r" type="HSlider" parent="."] +margin_left = 18.0 +margin_top = 21.0 +margin_right = 58.0 +margin_bottom = 29.0 +max_value = 31.0 + +[node name="slider_g" type="HSlider" parent="."] +margin_left = 18.0 +margin_top = 36.0 +margin_right = 58.0 +margin_bottom = 44.0 +max_value = 31.0 + +[node name="slider_b" type="HSlider" parent="."] +margin_left = 18.0 +margin_top = 51.0 +margin_right = 58.0 +margin_bottom = 59.0 +max_value = 31.0 + +[connection signal="value_changed" from="slider_r" to="." method="_on_slider_r_value_changed"] +[connection signal="value_changed" from="slider_g" to="." method="_on_slider_g_value_changed"] +[connection signal="value_changed" from="slider_b" to="." method="_on_slider_b_value_changed"]