aboutsummaryrefslogtreecommitdiff
path: root/game/src/Game/Model/UnitModel.gd
blob: e98d22a49e076c00ad942280c022130349585b85 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
class_name UnitModel
extends Node3D

var skeleton : Skeleton3D = null
var anim_player : AnimationPlayer = null
var anim_lib : AnimationLibrary = null
var sub_units : Array[UnitModel]
var meshes : Array[MeshInstance3D]

# COLOUR VARIABLES
@export_group("Colors")
@export var primary_colour : Color:
   set(col_in):
      primary_colour = col_in
      _set_shader_parameter(&"colour_primary", primary_colour)
      for unit : UnitModel in sub_units:
         unit.primary_colour = col_in

@export var secondary_colour: Color:
   set(col_in):
      secondary_colour = col_in
      _set_shader_parameter(&"colour_secondary", secondary_colour)
      for unit : UnitModel in sub_units:
         unit.secondary_colour = col_in

@export var tertiary_colour : Color:
   set(col_in):
      tertiary_colour = col_in
      _set_shader_parameter(&"colour_tertiary", tertiary_colour)
      for unit : UnitModel in sub_units:
         unit.tertiary_colour = col_in

# ANIMATION VARIABLES
@export_group("Animation")
@export var idle_anim : Animation:
   set(anim_in):
      load_animation("idle", anim_in)
      idle_anim = anim_in

@export var move_anim : Animation:
   set(anim_in):
      load_animation("move", anim_in)
      move_anim = anim_in

@export var attack_anim : Animation:
   set(anim_in):
      load_animation("attack", anim_in)
      attack_anim = anim_in

enum Anim { NONE, IDLE, MOVE, ATTACK }

const ANIMATION_LIBRARY : StringName = &"default_lib"
const ANIMATION_IDLE : String = ANIMATION_LIBRARY + "/idle"
const ANIMATION_MOVE : String = ANIMATION_LIBRARY + "/move"
const ANIMATION_ATTACK : String = ANIMATION_LIBRARY + "/attack"

@export var current_anim : Anim:
   set(anim_in):
      for unit : UnitModel in sub_units:
         unit.current_anim = anim_in

      if anim_player:
         match anim_in:
            Anim.IDLE:
               if idle_anim:
                  anim_player.set_current_animation(ANIMATION_IDLE)
                  _set_tex_scroll(scroll_speed_idle)
                  current_anim = Anim.IDLE
                  return
            Anim.MOVE:
               if move_anim:
                  anim_player.set_current_animation(ANIMATION_MOVE)
                  _set_tex_scroll(scroll_speed_move)
                  current_anim = Anim.MOVE
                  return
            Anim.ATTACK:
               if attack_anim:
                  anim_player.set_current_animation(ANIMATION_ATTACK)
                  _set_tex_scroll(scroll_speed_attack)
                  current_anim = Anim.ATTACK
                  return
            _: #None
               pass

         anim_player.stop()

      _set_tex_scroll(0.0)
      current_anim = Anim.NONE

# TEXTURE SCROLL SPEEDS (TANKS TRACKS AND SMOKE)
@export_subgroup("Texture_Scroll")
@export var scroll_speed_idle : float:
   set(speed_in):
      scroll_speed_idle = speed_in
      for unit : UnitModel in sub_units:
         unit.scroll_speed_idle = speed_in

@export var scroll_speed_move : float:
   set(speed_in):
      scroll_speed_move = speed_in
      for unit : UnitModel in sub_units:
         unit.scroll_speed_move = speed_in

@export var scroll_speed_attack : float:
   set(speed_in):
      scroll_speed_attack = speed_in
      for unit : UnitModel in sub_units:
         unit.scroll_speed_attack = speed_in

func unit_init() -> void:
   for child : Node in get_children():
      if child is MeshInstance3D:
         meshes.append(child)
      elif child is Skeleton3D:
         skeleton = child

func add_anim_player() -> void:
   anim_player = AnimationPlayer.new()
   anim_player.name = "anim_player"

   anim_lib = AnimationLibrary.new()
   anim_lib.resource_name = ANIMATION_LIBRARY
   anim_player.add_animation_library(ANIMATION_LIBRARY, anim_lib)

   add_child(anim_player)

func has_bone(bone_name : String) -> bool:
   return skeleton and skeleton.find_bone(bone_name) > -1

func attach_model(bone_name : String, model : Node3D) -> Error:
   if not model:
      push_error("Cannot attach null model to bone \"", bone_name, "\" of UnitModel ", get_name())
      return FAILED

   if not skeleton:
      push_error("Cannot attach model \"", model.get_name(), "\" to bone \"", bone_name, "\" of UnitModel ", get_name(), " - has no skeleton!")
      return FAILED

   var bone_idx : int = skeleton.find_bone(bone_name)
   if bone_idx < 0 or bone_idx >= skeleton.get_bone_count():
      push_error("Invalid bone \"", bone_name, "\" (index ", bone_idx, ") for attachment \"", model.get_name(), "\" to UnitModel \"", get_name(), "\"")
      return FAILED

   var bone_attachment := BoneAttachment3D.new()
   bone_attachment.name = bone_name
   bone_attachment.bone_idx = bone_idx
   bone_attachment.add_child(model)
   skeleton.add_child(bone_attachment)

   if model is UnitModel:
      sub_units.push_back(model)
      model.current_anim = current_anim
      model.primary_colour = primary_colour
      model.secondary_colour = secondary_colour
      model.tertiary_colour = tertiary_colour

   return OK

func _set_shader_parameter(param_name : StringName, param_val : Variant) -> void:
   for mesh : MeshInstance3D in meshes:
      mesh.set_instance_shader_parameter(param_name, param_val)

func _set_tex_scroll(speed : float) -> void:
   _set_shader_parameter(&"scroll_speed", speed)

func set_flag_index(index : int) -> void:
   _set_shader_parameter(&"flag_index", index)

func load_animation(prop_name : String, animIn : Animation) -> void:
   if not animIn:
      return
   if not anim_player:
      add_anim_player()
   anim_lib.add_animation(prop_name,animIn)