File size: 5,000 Bytes
8e8f673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# nodes.py
# Combined: SimpleNumberCounter, SimpleConstantNumber, SimpleLogicBoolean, StringFromList, LoadTextFile

import math

# ── Counter state ────────────────────────────────────────────────────────────
_counter_state = {"value": 0}


def wrapIndex(index, length):
    if length == 0:
        print("ezXY: Divide by zero error, returning 0.")
        return 0, 0
    index_mod = int(math.fmod(index, length))
    wraps = index // length
    return index_mod, wraps


class SimpleNumberCounter:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "mode":  (["increment", "decrement", "increment_to_stop", "decrement_to_stop"],),
                "stop":  ("FLOAT", {"default": 100.0, "min": 0.0, "max": 99999.0, "step": 1.0}),
                "start": ("INT",   {"default": 0, "min": 0, "max": 99999}),
                "step":  ("INT",   {"default": 1, "min": 0, "max": 99999}),
            },
            "optional": {
                "reset_bool": ("NUMBER",),
            }
        }

    FUNCTION = "count"
    CATEGORY = "Simple Utils"
    RETURN_TYPES = ("NUMBER", "FLOAT", "INT")
    RETURN_NAMES = ("number", "float", "int")

    @classmethod
    def IS_CHANGED(cls, **kwargs):
        return float("nan")

    def count(self, mode, stop, start, step, reset_bool=None):
        global _counter_state
        if reset_bool is not None and float(reset_bool) > 0:
            _counter_state["value"] = start
        v = _counter_state["value"]
        if mode in ("increment", "increment_to_stop"):
            next_v = v + step
            if next_v >= stop:
                next_v = start
            _counter_state["value"] = next_v
        else:
            next_v = v - step
            if next_v < 0:
                next_v = int(stop)
            _counter_state["value"] = next_v
        return (float(v), float(v), int(v))


class SimpleConstantNumber:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "value": ("FLOAT", {"default": 1.0, "min": -99999.0, "max": 99999.0, "step": 1.0}),
            }
        }

    FUNCTION = "output"
    CATEGORY = "Simple Utils"
    RETURN_TYPES = ("NUMBER", "FLOAT", "INT")
    RETURN_NAMES = ("NUMBER", "FLOAT", "INT")

    def output(self, value):
        return (float(value), float(value), int(value))


class SimpleLogicBoolean:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "boolean": ("BOOLEAN", {"default": True}),
            }
        }

    FUNCTION = "output"
    CATEGORY = "Simple Utils"
    RETURN_TYPES = ("BOOLEAN", "NUMBER", "INT", "FLOAT")
    RETURN_NAMES = ("BOOLEAN", "NUMBER", "INT", "FLOAT")

    def output(self, boolean):
        v = 1 if boolean else 0
        return (boolean, float(v), int(v), float(v))


class StringFromList:
    @classmethod
    def INPUT_TYPES(s):
        return {
            "required": {
                "list_input": ("STRING", {"forceInput": True},),
                "index": ("INT", {"default": 0, "min": -999, "max": 999, "step": 1}),
            },
        }

    RETURN_TYPES = ("STRING", "INT", "INT",)
    RETURN_NAMES = ("list item", "size", "wraps",)
    INPUT_IS_LIST = True
    OUTPUT_IS_LIST = (True, False, True)
    FUNCTION = "pick"
    CATEGORY = "ezXY/utility"

    def pick(self, list_input, index):
        length = len(list_input)
        wraps_list, item_list = [], []
        for i in index:
            index_mod, wraps = wrapIndex(i, length)
            wraps_list.append(wraps)
            item_list.append(list_input[index_mod])
        return (item_list, length, wraps_list,)


class LoadTextFile:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "file_path": ("STRING", {"default": "/input/yourfile.txt", "multiline": False}),
            }
        }

    FUNCTION = "load"
    CATEGORY = "Simple Utils"
    RETURN_TYPES = ("STRING",)
    RETURN_NAMES = ("STRING",)

    @classmethod
    def IS_CHANGED(cls, **kwargs):
        return float("nan")

    def load(self, file_path):
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                return (f.read(),)
        except Exception as e:
            print(f"[LoadTextFile] Error reading '{file_path}': {e}")
            return ("",)


NODE_CLASS_MAPPINGS = {
    "Number Counter":  SimpleNumberCounter,
    "Constant Number": SimpleConstantNumber,
    "Logic Boolean":   SimpleLogicBoolean,
    "StringFromList":  StringFromList,
    "LoadTextFile":    LoadTextFile,
}

NODE_DISPLAY_NAME_MAPPINGS = {
    "Number Counter":  "Number Counter (Simple)",
    "Constant Number": "Constant Number (Simple)",
    "Logic Boolean":   "Logic Boolean (Simple)",
    "StringFromList":  "String From List",
    "LoadTextFile":    "Load Text File (Simple)",
}