Skip to content

Commit 07df08c

Browse files
committed
Refactor HeightmapEditor to use MVC pattern with shared model
- Create HeightmapEditorModel with field definitions and business logic - Refactor Chili HeightmapEditor to use model for field/tool definitions - Implement RmlUi HeightmapEditor to use the same shared model - Both views now only contain UI-specific layout code - Eliminates duplication between Chili and RmlUi implementations
1 parent 4baddba commit 07df08c

File tree

4 files changed

+353
-129
lines changed

4 files changed

+353
-129
lines changed

scen_edit/view/map/heightmap_editor.lua

Lines changed: 105 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -10,82 +10,71 @@ HeightmapEditor:Register({
1010
order = 0,
1111
})
1212

13-
function HeightmapEditor:init()
13+
function HeightmapEditor:init(model)
1414
self:super("init")
15+
self.model = model or HeightmapEditorModel()
1516

16-
self:AddField(AssetField({
17-
name = "patternTexture",
18-
title = "Pattern:",
19-
rootDir = "brush_patterns/terrain/",
20-
expand = true,
21-
itemWidth = 65,
22-
itemHeight = 65,
23-
Validate = function(obj, value)
24-
if value == nil then
25-
return true
26-
end
27-
if not AssetField.Validate(obj, value) then
28-
return false
29-
end
30-
31-
local ext = Path.GetExt(value) or ""
32-
return table.ifind(SB_IMG_EXTS, ext), value
33-
end,
34-
Update = function(...)
35-
AssetField.Update(...)
36-
local texture = self.fields["patternTexture"].value
37-
SB.model.terrainManager:generateShape(texture)
17+
local fieldDefs = self.model:GetFieldDefinitions()
18+
for _, fieldDef in ipairs(fieldDefs) do
19+
if fieldDef.type == "asset" then
20+
self:AddField(AssetField({
21+
name = fieldDef.name,
22+
title = fieldDef.title,
23+
rootDir = fieldDef.rootDir,
24+
expand = fieldDef.expand,
25+
itemWidth = fieldDef.itemWidth,
26+
itemHeight = fieldDef.itemHeight,
27+
Validate = fieldDef.validateFunc,
28+
Update = function(...)
29+
AssetField.Update(...)
30+
local value = self.fields[fieldDef.name].value
31+
fieldDef.updateFunc(value)
32+
end
33+
}))
34+
elseif fieldDef.type == "numeric" then
35+
self:AddField(NumericField({
36+
name = fieldDef.name,
37+
value = fieldDef.value,
38+
minValue = fieldDef.min,
39+
maxValue = fieldDef.max,
40+
step = fieldDef.step,
41+
title = fieldDef.title,
42+
tooltip = fieldDef.tooltip,
43+
}))
44+
elseif fieldDef.type == "choice" then
45+
self:AddField(ChoiceField({
46+
name = fieldDef.name,
47+
items = fieldDef.items,
48+
tooltip = fieldDef.tooltip,
49+
}))
3850
end
39-
}))
40-
41-
self.btnAddState = TabbedPanelButton({
42-
x = 0,
43-
y = 0,
44-
tooltip = "Left Click to add height, Right Click to remove height",
45-
children = {
46-
TabbedPanelImage({ file = Path.Join(SB.DIRS.IMG, 'up-card.png') }),
47-
TabbedPanelLabel({ caption = "Add" }),
48-
},
49-
OnClick = {
50-
function()
51-
SB.stateManager:SetState(TerrainShapeModifyState(self))
52-
end
53-
},
54-
})
51+
end
5552

56-
self.btnSetState = TabbedPanelButton({
57-
x = 70,
58-
y = 0,
59-
tooltip = "Left Click to set height. Right click to sample height",
60-
children = {
61-
TabbedPanelImage({ file = Path.Join(SB.DIRS.IMG, 'terrain-set.png') }),
62-
TabbedPanelLabel({ caption = "Set" }),
63-
},
64-
OnClick = {
65-
function()
66-
SB.stateManager:SetState(TerrainSetState(self))
67-
end
68-
},
69-
})
53+
local toolModes = self.model:GetToolModes()
54+
self.toolButtons = {}
55+
for i, toolMode in ipairs(toolModes) do
56+
local x = (i - 1) * 70
57+
local btn = TabbedPanelButton({
58+
x = x,
59+
y = 0,
60+
tooltip = toolMode.tooltip,
61+
children = {
62+
TabbedPanelImage({ file = Path.Join(SB.DIRS.IMG, toolMode.icon) }),
63+
TabbedPanelLabel({ caption = toolMode.caption }),
64+
},
65+
OnClick = {
66+
function()
67+
self.model:ActivateTool(toolMode.id, self)
68+
end
69+
},
70+
})
71+
self.toolButtons[toolMode.id] = btn
72+
end
7073

71-
self.btnSmoothState = TabbedPanelButton({
72-
x = 140,
73-
y = 0,
74-
tooltip = "Click to smooth terrain",
75-
children = {
76-
TabbedPanelImage({ file = Path.Join(SB.DIRS.IMG, 'terrain-smooth.png') }),
77-
TabbedPanelLabel({ caption = "Smooth" }),
78-
},
79-
OnClick = {
80-
function()
81-
SB.stateManager:SetState(TerrainSmoothState(self))
82-
end
83-
},
84-
})
8574
self:AddDefaultKeybinding({
86-
self.btnAddState,
87-
self.btnSetState,
88-
self.btnSmoothState
75+
self.toolButtons["add"],
76+
self.toolButtons["set"],
77+
self.toolButtons["smooth"]
8978
})
9079

9180
self:AddControl("btn-show-elevation", {
@@ -95,54 +84,34 @@ function HeightmapEditor:init()
9584
height = 40,
9685
OnClick = {
9786
function()
98-
Spring.SendCommands('showelevation')
87+
self.model:ShowElevation()
9988
end
10089
}
10190
},
10291
})
10392

104-
self:AddField(NumericField({
105-
name = "size",
106-
value = 100,
107-
minValue = 10,
108-
maxValue = 5000,
109-
title = "Size:",
110-
tooltip = "Size of the height brush",
111-
}))
112-
self:AddField(NumericField({
113-
name = "rotation",
114-
value = 0,
115-
minValue = -360,
116-
maxValue = 360,
117-
title = "Rotation:",
118-
tooltip = "Rotation of the shape",
119-
}))
120-
self:AddField(NumericField({
121-
name = "strength",
122-
value = 10,
123-
step = 0.1,
124-
title = "Strength:",
125-
tooltip = "Strength of the height map tool",
126-
}))
127-
self:AddField(NumericField({
128-
name = "height",
129-
value = 10,
130-
step = 0.1,
131-
title = "Height:",
132-
tooltip = "Goal height",
133-
}))
134-
self:AddField(ChoiceField({
135-
name = "applyDir",
136-
items = {"Both", "Only Raise", "Only Lower"},
137-
tooltip = "Whether terrain should be only lowered, raised or both.",
138-
}))
13993
self:Update("size")
140-
self:SetInvisibleFields("applyDir")
94+
local visibleFields = self.model:GetVisibleFieldsForMode(self.model:GetCurrentMode())
95+
local allFields = {"patternTexture", "size", "rotation", "strength", "height", "applyDir"}
96+
local invisibleFields = {}
97+
for _, field in ipairs(allFields) do
98+
local isVisible = false
99+
for _, vf in ipairs(visibleFields) do
100+
if vf == field then
101+
isVisible = true
102+
break
103+
end
104+
end
105+
if not isVisible then
106+
table.insert(invisibleFields, field)
107+
end
108+
end
109+
self:SetInvisibleFields(unpack(invisibleFields))
141110

142111
local children = {
143-
self.btnAddState,
144-
self.btnSetState,
145-
self.btnSmoothState,
112+
self.toolButtons["add"],
113+
self.toolButtons["set"],
114+
self.toolButtons["smooth"],
146115
ScrollPanel:New {
147116
x = 0,
148117
y = 70,
@@ -158,26 +127,42 @@ function HeightmapEditor:init()
158127
end
159128

160129
function HeightmapEditor:OnLeaveState(state)
161-
for _, btn in pairs({self.btnAddState, self.btnSmoothState, self.btnSetState}) do
130+
for _, btn in pairs(self.toolButtons) do
162131
btn:SetPressedState(false)
163132
end
164133
end
165134

166135
function HeightmapEditor:OnEnterState(state)
167-
local btn
136+
local modeId
168137
if state:is_A(TerrainShapeModifyState) then
169-
self:SetInvisibleFields("applyDir")
170-
btn = self.btnAddState
138+
modeId = "add"
171139
elseif state:is_A(TerrainSetState) then
172-
self:SetInvisibleFields()
173-
btn = self.btnSetState
140+
modeId = "set"
174141
elseif state:is_A(TerrainSmoothState) then
175-
self:SetInvisibleFields("applyDir")
176-
btn = self.btnSmoothState
142+
modeId = "smooth"
143+
end
144+
145+
self.model:SetMode(modeId)
146+
self.toolButtons[modeId]:SetPressedState(true)
147+
148+
local visibleFields = self.model:GetVisibleFieldsForMode(modeId)
149+
local allFields = {"patternTexture", "size", "rotation", "strength", "height", "applyDir"}
150+
local invisibleFields = {}
151+
for _, field in ipairs(allFields) do
152+
local isVisible = false
153+
for _, vf in ipairs(visibleFields) do
154+
if vf == field then
155+
isVisible = true
156+
break
157+
end
158+
end
159+
if not isVisible then
160+
table.insert(invisibleFields, field)
161+
end
177162
end
178-
btn:SetPressedState(true)
163+
self:SetInvisibleFields(unpack(invisibleFields))
179164
end
180165

181166
function HeightmapEditor:IsValidState(state)
182-
return state:is_A(AbstractHeightmapEditingState)
167+
return self.model:IsValidState(state)
183168
end

0 commit comments

Comments
 (0)