summaryrefslogtreecommitdiffhomepage
path: root/dragon/hotload.rb
blob: 1cb062a06c9573ffca8858b29d2a1eff9d8af6fd (plain)
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
# coding: utf-8
# Copyright 2019 DragonRuby LLC
# MIT License
# hotlaod.rb has been released under MIT (*only this file*).

module GTK
  class Runtime
    # @visibility private
    module Hotload
      def hotload_init
        @hotload_if_needed = 0
        @mailbox_if_needed = 0
        @file_mtimes = { }
        @suppress_mailbox = true
        files_to_reload.each { |f| init_mtimes f }
        init_mtimes 'app/mailbox.rb'
      end

      def hotload_on_write_file file_name
        return unless file_name.include? 'mailbox.rb'
        @mailbox_if_needed = :force
      end

      def files_to_reload
        if @rcb_release_mode
          core_files_to_reload + @required_files
        else
          [
            'dragon/docs.rb',
            'dragon/help.rb',
            'dragon/kernel_docs.rb',
            'dragon/kernel.rb',
            'dragon/easing.rb',
            'dragon/top_level.rb',
            'dragon/log.rb',
            'dragon/geometry.rb',
            'dragon/attr_gtk.rb',
            'dragon/attr_sprite.rb',
            'dragon/object.rb',
            'dragon/class.rb',
            'dragon/string.rb',
            'dragon/entity.rb',
            'dragon/strict_entity.rb',
            'dragon/open_entity.rb',
            'dragon/serialize.rb',
            'dragon/primitive.rb',
            'dragon/nil_class_false_class.rb',
            'dragon/symbol.rb',
            'dragon/numeric_deprecated.rb',
            'dragon/numeric.rb',
            'dragon/hash.rb',
            'dragon/outputs_deprecated.rb',
            'dragon/array_docs.rb',
            'dragon/array.rb',
            'dragon/outputs.rb',
            'dragon/inputs.rb',
            'dragon/mouse_docs.rb',
            'dragon/recording.rb',
            'dragon/grid.rb',
            'dragon/layout.rb',
            'dragon/args_deprecated.rb',
            'dragon/fn.rb',
            'dragon/args.rb',
            'dragon/console_prompt.rb',
            'dragon/console_menu.rb',
            'dragon/console.rb',
            'dragon/assert.rb',
            'dragon/tests.rb',
            'dragon/controller_config.rb',
            'dragon/runtime/draw.rb',
            'dragon/runtime/deprecated.rb',
            'dragon/runtime/framerate.rb',
            'dragon/runtime/c_bridge.rb',
            'dragon/runtime/hotload.rb',
            'dragon/runtime/backup.rb',
            'dragon/runtime/async_require.rb',
            'dragon/runtime/autocomplete.rb',
            'dragon/api.rb',
            'dragon/runtime.rb',
            'dragon/trace.rb',
            'dragon/readme_docs.rb',
            'dragon/hotload_client.rb',
            'dragon/ios_wizard.rb',
            'dragon/itch_wizard.rb',
          ] + core_files_to_reload + @required_files
        end
      end

      def core_files_to_reload
        [
          'repl.rb',
          'app/main.rb',
          'app/repl.rb',
          'app/tests.rb',
          'app/test.rb',
          'app/stdin.rb'
        ]
      end

      def init_mtimes file
        current_key = "current_#{file}".to_sym
        last_key = "last_#{file}".to_sym
        @file_mtimes[current_key] ||= @ffi_file.mtime(file)
        @file_mtimes[last_key] ||= @ffi_file.mtime(file)
      end

      def hotload_source_files
        @hotload_if_needed += 1
        return unless @hotload_if_needed == 60
        @hotload_if_needed = 0
        files_to_reload.each { |f| reload_if_needed f }
        console.enable
      end

      def mailbox_timeout
        if @suppress_mailbox
          60
        else
          3
        end
      end

      def check_mailbox
        if @mailbox_if_needed == :force # lol
          reload_if_needed 'app/mailbox.rb', true
          @mailbox_if_needed = 1
          return
        end
        @mailbox_if_needed += 1
        return unless @mailbox_if_needed.mod_zero? mailbox_timeout
        @mailbox_if_needed = 1
        reload_if_needed 'app/mailbox.rb'
      end

      def hotload_if_needed
        hotload_source_files
        check_mailbox
      end

      def on_load_succeeded file
        @rcb_sender.files_reloaded << file
        @rcb_sender.reloaded_files << file
        Trace.untrace_classes!
      end

      def reload_if_needed file, force = false
        current_key = "current_#{file}".to_sym
        last_key = "last_#{file}".to_sym
        @file_mtimes[current_key] ||= nil
        @file_mtimes[last_key] ||= nil
        @file_mtimes[current_key] = @ffi_file.mtime(file)
        return if !force && @file_mtimes[last_key] == @file_mtimes[current_key]
        on_load_succeeded file if reload_ruby_file file
        @file_mtimes[last_key] = @file_mtimes[current_key]
      end
    end
  end
end